-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 == Administrivia ==
This is my first patch. I have emailed in the signed copyright transfer documents already. Several versions of this patch have been sent to the mailing list already. I believe that I have incorporated all comments into the attached patches. === Description === As required by the C and C++ standards, gcc automatically converts floating point numbers to lower precision or integer values. Silently converting these values is a problem for numerical programs. GCC already has a flag -Wconversion which does warn about these conversions, but -Wconversion also warns about integer conversion which means for many programs the number of warnings will be large. This patch adds a -Wfloat-conversion that only warns on float conversions. Here are three examples that are warned by this new flag: int main(int argc, char ** argv) { int i = 3.14; return i; } int foo(double x) { return x; } float foo2(double x) { return x; } Additional examples can be seen in the new_testcase variants. The -Wfloat-conversion is enabled by -Wconversion (since it is a subset) It was suggested on the discussion for bug 53001 that this be enabled by - -Wextra, but this version of the patch does not because that requires additional changes to other parts of gcc to still be able to bootstrap with -Werror since they rely on C and C++'s implicit conversion from floating point to integer types. I am not certain that c.opt was modified correctly. There are three different variants attached, they are identical but for the testcases, so see that section for details on the differences. Only one of them should be applied. == Testcases == There are three different methods of doing the testcase for these. 0. warn_float_patch_simple_trunk.diff This version changes the existing tests to check for float-coversion instead of conversion in the warning text. Since the testcases already check for floating conversion in warnings, this is a possible method of doing this. 1. warn_float_patch_and_new_testcase.diff This adds a new testcase and checks for float-conversion in the warning. This will add somewhat more time for running the testcases compared to version 1 while still testing more or less the same code paths. This does however check that the warning occurs when - -Wconversion is not used. 2. warn_float_patch_and_new_testcase2.diff This is the same as 1., but the warning check is more specific. So for example we have lines like: fsi (3.1f); /* { dg-warning "conversion to 'int' alters 'float' constant valu e" } */ I am worried (possibly groundlessly) that this might not pass the testcase on machines with different types that are available. If you have a strong opinion or good reasons on which of these you prefer, please tell me. == Change logs == Changelog for warn_float_patch_simple_trunk.diff: Splitting out a -Wfloat-conversion from -Wconversion for conversions that lower floating point number precision or conversion from floating point numbers to integers * c-family/c-common.c Switching unsafe_conversion_p to return an enumeration with more detail, and conversion_warning to use this information. * c-family/c-common.h Adding conversion_safety enumeration and switching return type of unsafe_conversion_p * c-family/c.opt Adding new warning float-conversion and enabling it -Wconversion * doc/invoke.texi Adding documentation about -Wfloat-conversion * testsuite/c-c++-common/Wconversion-real.c Switching tests to use float-conversion * testsuite/gcc.dg/Wconversion-real-integer.c Switching tests to use float-conversion * testsuite/gcc.dg/pr35635.c Switching tests to use float-conversion Changelog for warn_float_patch_and_new_testcase.diff and warn_float_patch_and_new_testcase2.diff: Splitting out a -Wfloat-conversion from -Wconversion for conversions that lower floating point number precision or conversion from floating point numbers to integers * c-family/c-common.c Switching unsafe_conversion_p to return an enumeration with more detail, and conversion_warning to use this information. * c-family/c-common.h Adding conversion_safety enumeration and switching return type of unsafe_conversion_p * c-family/c.opt Adding new warning float-conversion and enabling it -Wconversion * doc/invoke.texi Adding documentation about -Wfloat-conversion * testsuite/c-c++-common/Wfloat-conversion.c Copies relevant tests from c-c++-common/Wconversion-real.c, gcc.dg/Wconversion-real-integer.c and gcc.dg/pr35635.c into new testcase for ones that are warned about by -Wfloat-conversion == Bootstrapping and testing == Tested bootstrap on x86_64-unknown-linux-gnu for - --enable-languages=c,c++,fortran,java,lto,objc with trunk on 203640 for variants 1. and 2. Thank you for consideration of this patch. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBAgAGBQJSbR4RAAoJEFeOW05LP1fawCIH/32HxziKkBeFL8b1nv+fJw9N DJpCyser7djK6mG3hBHJaNEUjwR/EqMPt2jlc2kXBTQ1PlZ1feZ9fMrsAPokSMNd KZqp8nDkKxPpBqpCeVhpe801SIMe0XLDu+acfgzy1m560bQzsztjpZDjMP7Ilfa+ iNm0ih9Iq/5yPiA6WaJ3UfUqTz4NvsEXYGXi3SPJRt0+FmMnZqVIQHbUn3bnXNt8 LdTXeJv206OTr0kzSSa78i74SiDzHghfpvCcoOqZFjA0xvLm55sQ9cpu1b8nZKhw hEp2gG9xOpsF8UiNvvK9mWCZgkoShXCT0d3yns1eJTbXLMHlGLs7f7lyrVDyIZE= =xJms -----END PGP SIGNATURE-----
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 203640) +++ gcc/c-family/c-common.c (working copy) @@ -2518,7 +2518,7 @@ shorten_binary_op (tree result_type, tre } /* Checks if expression EXPR of real/integer type cannot be converted - to the real/integer type TYPE. Function returns true when: + to the real/integer type TYPE. Function returns non-zero when: * EXPR is a constant which cannot be exactly converted to TYPE * EXPR is not a constant and size of EXPR's type > than size of TYPE, for EXPR type and TYPE being both integers or both real. @@ -2526,12 +2526,12 @@ shorten_binary_op (tree result_type, tre * 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 - does not return true in that case. Function can produce signedness - warnings if PRODUCE_WARNS is true. */ -bool + can return SAFE_CONVERSION (zero) in that case. Function can produce + signedness warnings if PRODUCE_WARNS is true. */ +enum conversion_safety unsafe_conversion_p (tree type, tree expr, bool produce_warns) { - bool give_warning = false; + enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */ tree expr_type = TREE_TYPE (expr); location_t loc = EXPR_LOC_OR_HERE (expr); @@ -2543,7 +2543,7 @@ unsafe_conversion_p (tree type, tree exp && TREE_CODE (type) == INTEGER_TYPE) { if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type))) - give_warning = true; + give_warning = UNSAFE_REAL; } /* Warn for an integer constant that does not fit into integer type. */ else if (TREE_CODE (expr_type) == INTEGER_TYPE @@ -2564,7 +2564,7 @@ unsafe_conversion_p (tree type, tree exp " constant value to negative integer"); } else - give_warning = true; + give_warning = UNSAFE_OTHER; } else if (TREE_CODE (type) == REAL_TYPE) { @@ -2573,7 +2573,7 @@ unsafe_conversion_p (tree type, tree exp { REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) - give_warning = true; + give_warning = UNSAFE_REAL; } /* Warn for a real constant that does not fit into a smaller real type. */ @@ -2582,7 +2582,7 @@ unsafe_conversion_p (tree type, tree exp { REAL_VALUE_TYPE a = TREE_REAL_CST (expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) - give_warning = true; + give_warning = UNSAFE_REAL; } } } @@ -2591,7 +2591,7 @@ unsafe_conversion_p (tree type, tree exp /* Warn for real types converted to integer types. */ if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == INTEGER_TYPE) - give_warning = true; + give_warning = UNSAFE_REAL; else if (TREE_CODE (expr_type) == INTEGER_TYPE && TREE_CODE (type) == INTEGER_TYPE) @@ -2629,7 +2629,7 @@ unsafe_conversion_p (tree type, tree exp && int_fits_type_p (op1, c_common_signed_type (type)) && int_fits_type_p (op1, c_common_unsigned_type (type)))) - return false; + return SAFE_CONVERSION; /* If constant is unsigned and fits in the target type, then the result will also fit. */ else if ((TREE_CODE (op0) == INTEGER_CST @@ -2638,12 +2638,12 @@ unsafe_conversion_p (tree type, tree exp || (TREE_CODE (op1) == INTEGER_CST && unsigned1 && int_fits_type_p (op1, type))) - return false; + return SAFE_CONVERSION; } } /* Warn for integer types converted to smaller integer types. */ if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) - give_warning = true; + give_warning = UNSAFE_OTHER; /* When they are the same width but different signedness, then the value may change. */ @@ -2679,14 +2679,14 @@ unsafe_conversion_p (tree type, tree exp if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound) || !exact_real_truncate (TYPE_MODE (type), &real_high_bound)) - give_warning = true; + give_warning = UNSAFE_OTHER; } /* Warn for real types converted to smaller real types. */ else if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) - give_warning = true; + give_warning = UNSAFE_REAL; } return give_warning; @@ -2700,8 +2700,9 @@ conversion_warning (tree type, tree expr { tree expr_type = TREE_TYPE (expr); location_t loc = EXPR_LOC_OR_HERE (expr); + enum conversion_safety conversion_kind; - if (!warn_conversion && !warn_sign_conversion) + if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion) return; switch (TREE_CODE (expr)) @@ -2728,7 +2729,12 @@ conversion_warning (tree type, tree expr case REAL_CST: case INTEGER_CST: - if (unsafe_conversion_p (type, expr, true)) + conversion_kind = unsafe_conversion_p (type, expr, true); + if (conversion_kind == UNSAFE_REAL) + warning_at (loc, OPT_Wfloat_conversion, + "conversion to %qT alters %qT constant value", + type, expr_type); + else if (conversion_kind) warning_at (loc, OPT_Wconversion, "conversion to %qT alters %qT constant value", type, expr_type); @@ -2747,7 +2753,12 @@ conversion_warning (tree type, tree expr } default: /* 'expr' is not a constant. */ - if (unsafe_conversion_p (type, expr, true)) + conversion_kind = unsafe_conversion_p (type, expr, true); + if (conversion_kind == UNSAFE_REAL) + warning_at (loc, OPT_Wfloat_conversion, + "conversion to %qT from %qT may alter its value", + type, expr_type); + else if (conversion_kind) warning_at (loc, OPT_Wconversion, "conversion to %qT from %qT may alter its value", type, expr_type); Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 203640) +++ gcc/c-family/c-common.h (working copy) @@ -685,6 +685,16 @@ struct visibility_flags unsigned inlines_hidden : 1; /* True when -finlineshidden in effect. */ }; +/* These enumerators are possible types of unsafe conversions. + SAFE_CONVERSION The conversion is safe + UNSAFE_OTHER Another type of conversion with problems + UNSAFE_SIGN Conversion between signed and unsigned integers + which are all warned about immediately, so this is unused + UNSAFE_REAL Conversions that reduce the precision of reals + including conversions from reals to integers + */ +enum conversion_safety { SAFE_CONVERSION = 0, UNSAFE_OTHER, UNSAFE_SIGN, UNSAFE_REAL }; + /* Global visibility options. */ extern struct visibility_flags visibility_options; @@ -738,7 +748,7 @@ extern tree c_common_signed_type (tree); extern tree c_common_signed_or_unsigned_type (int, tree); extern void c_common_init_ts (void); extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int); -extern bool unsafe_conversion_p (tree, tree, bool); +extern enum conversion_safety unsafe_conversion_p (tree, tree, bool); extern bool decl_with_nonnull_addr_p (const_tree); extern tree c_fully_fold (tree, bool, bool *); extern tree decl_constant_value_for_optimization (tree); Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 203640) +++ gcc/c-family/c.opt (working copy) @@ -387,6 +387,10 @@ Werror-implicit-function-declaration C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration) This switch is deprecated; use -Werror=implicit-function-declaration instead +Wfloat-conversion +C ObjC C++ ObjC++ Var(warn_float_conversion) LangEnabledBy(C ObjC C++ ObjC++,Wconversion) +Warn for implicit type conversions that cause loss of floating point precision + Wfloat-equal C ObjC C++ ObjC++ Var(warn_float_equal) Warning Warn if testing floating point numbers for equality Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 203640) +++ gcc/doc/invoke.texi (working copy) @@ -263,7 +263,8 @@ Objective-C and Objective-C++ Dialects}. -Wpointer-arith -Wno-pointer-to-int-cast @gol -Wredundant-decls -Wno-return-local-addr @gol -Wreturn-type -Wsequence-point -Wshadow @gol --Wsign-compare -Wsign-conversion -Wsizeof-pointer-memaccess @gol +-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol +-Wsizeof-pointer-memaccess @gol -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol -Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol @@ -4570,6 +4571,14 @@ value, like assigning a signed integer e integer variable. An explicit cast silences the warning. In C, this option is enabled also by @option{-Wconversion}. +@item -Wfloat-conversion +@opindex Wfloat-conversion +@opindex Wno-float-conversion +Warn for implicit conversions that reduce the precision of a real value. +This includes conversions from real to integer, and from higher precision +real to lower precision real values. This option is also enabled by +@option{-Wconversion}. + @item -Wsizeof-pointer-memaccess @opindex Wsizeof-pointer-memaccess @opindex Wno-sizeof-pointer-memaccess Index: gcc/testsuite/c-c++-common/Wfloat-conversion.c =================================================================== --- gcc/testsuite/c-c++-common/Wfloat-conversion.c (working copy) +++ gcc/testsuite/c-c++-common/Wfloat-conversion.c (working copy) @@ -1,85 +1,58 @@ /* Test for diagnostics for Wconversion for floating-point. */ /* { dg-do compile } */ -/* { dg-skip-if "doubles are floats" { "avr-*-*" } { "*" } { "" } } */ -/* { dg-options "-std=c99 -Wconversion" { target c } } */ -/* { dg-options "-Wconversion" { target c++ } } */ +/* { dg-options "-std=c99 -Wfloat-conversion" { target c } } */ +/* { dg-options "-Wfloat-conversion" { target c++ } } */ /* { dg-require-effective-target large_double } */ +/* { dg-require-effective-target int32plus } */ +/* { dg-require-effective-target double64plus } */ +#include <limits.h> float vfloat; double vdouble; long double vlongdouble; +int bar; +void fsi (signed int x); +void fui (unsigned int x); void ffloat (float f); void fdouble (double d); void flongdouble (long double ld); void h (void) { + unsigned int ui = 3; + int si = 3; + unsigned char uc = 3; + signed char sc = 3; float f = 0; double d = 0; long double ld = 0; - ffloat (3.1); /* { dg-warning "conversion" } */ - vfloat = 3.1; /* { dg-warning "conversion" } */ - ffloat (3.1L); /* { dg-warning "conversion" } */ - vfloat = 3.1L; /* { dg-warning "conversion" } */ - fdouble (3.1L); /* { dg-warning "conversion" "" { target large_long_double } } */ - vdouble = 3.1L; /* { dg-warning "conversion" "" { target large_long_double } } */ - ffloat (vdouble); /* { dg-warning "conversion" } */ - vfloat = vdouble; /* { dg-warning "conversion" } */ - ffloat (vlongdouble); /* { dg-warning "conversion" } */ - vfloat = vlongdouble; /* { dg-warning "conversion" } */ - fdouble (vlongdouble); /* { dg-warning "conversion" "" { target large_long_double } } */ - vdouble = vlongdouble; /* { dg-warning "conversion" "" { target large_long_double } } */ - - - ffloat ((float) 3.1); - vfloat = (float) 3.1; - ffloat ((float) 3.1L); - vfloat = (float) 3.1L; - fdouble ((double) 3.1L); - vdouble = (double) 3.1L; - ffloat ((float) vdouble); - vfloat = (float) vdouble; - ffloat ((float) vlongdouble); - vfloat = (float) vlongdouble; - fdouble ((double) vlongdouble); - vdouble = (double) vlongdouble; - - - ffloat (3.0); - vfloat = 3.0; - ffloat (3.1f); - vfloat = 3.1f; - ffloat (0.25L); - vfloat = 0.25L; - - - fdouble (3.0); - vdouble = 3.0; - fdouble (3.1f); - vdouble = 3.1f; - fdouble (0.25L); - vdouble = 0.25L; - - flongdouble (3.0); - vlongdouble = 3.0; - flongdouble (3.1f); - vlongdouble = 3.1f; - flongdouble (0.25L); - vlongdouble = 0.25L; - - ffloat (f); - vfloat = f; - fdouble (f); - vdouble = f; - fdouble (d); - vdouble = d; - flongdouble (f); - vlongdouble = f; - flongdouble (d); - vlongdouble = d; - flongdouble (ld); - vlongdouble = ld; + ffloat (3.1); /* { dg-warning "conversion to 'float' alters 'double' constant value" } */ + vfloat = 3.1; /* { dg-warning "conversion to 'float' alters 'double' constant value" } */ + ffloat (3.1L); /* { dg-warning "conversion to 'float' alters 'long double' constant value" } */ + vfloat = 3.1L; /* { dg-warning "conversion to 'float' alters 'long double' constant value" } */ + fdouble (3.1L); /* { dg-warning "conversion to 'double' alters 'long double' constant value" "" { target large_long_double } } */ + vdouble = 3.1L; /* { dg-warning "conversion to 'double' alters 'long double' constant value" "" { target large_long_double } } */ + ffloat (vdouble); /* { dg-warning "conversion to 'float' from 'double' may alter its value" } */ + vfloat = vdouble; /* { dg-warning "conversion to 'float' from 'double' may alter its value" } */ + ffloat (vlongdouble); /* { dg-warning "conversion to 'float' from 'long double' may alter its value" } */ + vfloat = vlongdouble; /* { dg-warning "conversion to 'float' from 'long double' may alter its value" } */ + fdouble (vlongdouble); /* { dg-warning "conversion to 'double' from 'long double' may alter its value" "" { target large_long_double } } */ + vdouble = vlongdouble; /* { dg-warning "conversion to 'double' from 'long double' may alter its value" "" { target large_long_double } } */ + + fsi (3.1f); /* { dg-warning "conversion to 'int' alters 'float' constant value" } */ + si = 3.1f; /* { dg-warning "conversion to 'int' alters 'float' constant value" } */ + fsi (3.1); /* { dg-warning "conversion to 'int' alters 'double' constant value" } */ + si = 3.1; /* { dg-warning "conversion to 'int' alters 'double' constant value" } */ + fsi (d); /* { dg-warning "conversion to 'int' from 'double' may alter its value" } */ + si = d; /* { dg-warning "conversion to 'int' from 'double' may alter its value" } */ + ffloat (INT_MAX); /* { dg-warning "conversion to 'float' alters 'int' constant value" } */ + vfloat = INT_MAX; /* { dg-warning "conversion to 'float' alters 'int' constant value" } */ + ffloat (16777217); /* { dg-warning "conversion to 'float' alters 'int' constant value" } */ + vfloat = 16777217; /* { dg-warning "conversion to 'float' alters 'int' constant value" } */ + + sc = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion to 'signed char' alters 'double' constant value" } */ + uc = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion to 'unsigned char' alters 'double' constant value" } */ }
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 203640) +++ gcc/c-family/c-common.c (working copy) @@ -2518,7 +2518,7 @@ shorten_binary_op (tree result_type, tre } /* Checks if expression EXPR of real/integer type cannot be converted - to the real/integer type TYPE. Function returns true when: + to the real/integer type TYPE. Function returns non-zero when: * EXPR is a constant which cannot be exactly converted to TYPE * EXPR is not a constant and size of EXPR's type > than size of TYPE, for EXPR type and TYPE being both integers or both real. @@ -2526,12 +2526,12 @@ shorten_binary_op (tree result_type, tre * 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 - does not return true in that case. Function can produce signedness - warnings if PRODUCE_WARNS is true. */ -bool + can return SAFE_CONVERSION (zero) in that case. Function can produce + signedness warnings if PRODUCE_WARNS is true. */ +enum conversion_safety unsafe_conversion_p (tree type, tree expr, bool produce_warns) { - bool give_warning = false; + enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */ tree expr_type = TREE_TYPE (expr); location_t loc = EXPR_LOC_OR_HERE (expr); @@ -2543,7 +2543,7 @@ unsafe_conversion_p (tree type, tree exp && TREE_CODE (type) == INTEGER_TYPE) { if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type))) - give_warning = true; + give_warning = UNSAFE_REAL; } /* Warn for an integer constant that does not fit into integer type. */ else if (TREE_CODE (expr_type) == INTEGER_TYPE @@ -2564,7 +2564,7 @@ unsafe_conversion_p (tree type, tree exp " constant value to negative integer"); } else - give_warning = true; + give_warning = UNSAFE_OTHER; } else if (TREE_CODE (type) == REAL_TYPE) { @@ -2573,7 +2573,7 @@ unsafe_conversion_p (tree type, tree exp { REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) - give_warning = true; + give_warning = UNSAFE_REAL; } /* Warn for a real constant that does not fit into a smaller real type. */ @@ -2582,7 +2582,7 @@ unsafe_conversion_p (tree type, tree exp { REAL_VALUE_TYPE a = TREE_REAL_CST (expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) - give_warning = true; + give_warning = UNSAFE_REAL; } } } @@ -2591,7 +2591,7 @@ unsafe_conversion_p (tree type, tree exp /* Warn for real types converted to integer types. */ if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == INTEGER_TYPE) - give_warning = true; + give_warning = UNSAFE_REAL; else if (TREE_CODE (expr_type) == INTEGER_TYPE && TREE_CODE (type) == INTEGER_TYPE) @@ -2629,7 +2629,7 @@ unsafe_conversion_p (tree type, tree exp && int_fits_type_p (op1, c_common_signed_type (type)) && int_fits_type_p (op1, c_common_unsigned_type (type)))) - return false; + return SAFE_CONVERSION; /* If constant is unsigned and fits in the target type, then the result will also fit. */ else if ((TREE_CODE (op0) == INTEGER_CST @@ -2638,12 +2638,12 @@ unsafe_conversion_p (tree type, tree exp || (TREE_CODE (op1) == INTEGER_CST && unsigned1 && int_fits_type_p (op1, type))) - return false; + return SAFE_CONVERSION; } } /* Warn for integer types converted to smaller integer types. */ if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) - give_warning = true; + give_warning = UNSAFE_OTHER; /* When they are the same width but different signedness, then the value may change. */ @@ -2679,14 +2679,14 @@ unsafe_conversion_p (tree type, tree exp if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound) || !exact_real_truncate (TYPE_MODE (type), &real_high_bound)) - give_warning = true; + give_warning = UNSAFE_OTHER; } /* Warn for real types converted to smaller real types. */ else if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) - give_warning = true; + give_warning = UNSAFE_REAL; } return give_warning; @@ -2700,8 +2700,9 @@ conversion_warning (tree type, tree expr { tree expr_type = TREE_TYPE (expr); location_t loc = EXPR_LOC_OR_HERE (expr); + enum conversion_safety conversion_kind; - if (!warn_conversion && !warn_sign_conversion) + if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion) return; switch (TREE_CODE (expr)) @@ -2728,7 +2729,12 @@ conversion_warning (tree type, tree expr case REAL_CST: case INTEGER_CST: - if (unsafe_conversion_p (type, expr, true)) + conversion_kind = unsafe_conversion_p (type, expr, true); + if (conversion_kind == UNSAFE_REAL) + warning_at (loc, OPT_Wfloat_conversion, + "conversion to %qT alters %qT constant value", + type, expr_type); + else if (conversion_kind) warning_at (loc, OPT_Wconversion, "conversion to %qT alters %qT constant value", type, expr_type); @@ -2747,7 +2753,12 @@ conversion_warning (tree type, tree expr } default: /* 'expr' is not a constant. */ - if (unsafe_conversion_p (type, expr, true)) + conversion_kind = unsafe_conversion_p (type, expr, true); + if (conversion_kind == UNSAFE_REAL) + warning_at (loc, OPT_Wfloat_conversion, + "conversion to %qT from %qT may alter its value", + type, expr_type); + else if (conversion_kind) warning_at (loc, OPT_Wconversion, "conversion to %qT from %qT may alter its value", type, expr_type); Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 203640) +++ gcc/c-family/c-common.h (working copy) @@ -685,6 +685,16 @@ struct visibility_flags unsigned inlines_hidden : 1; /* True when -finlineshidden in effect. */ }; +/* These enumerators are possible types of unsafe conversions. + SAFE_CONVERSION The conversion is safe + UNSAFE_OTHER Another type of conversion with problems + UNSAFE_SIGN Conversion between signed and unsigned integers + which are all warned about immediately, so this is unused + UNSAFE_REAL Conversions that reduce the precision of reals + including conversions from reals to integers + */ +enum conversion_safety { SAFE_CONVERSION = 0, UNSAFE_OTHER, UNSAFE_SIGN, UNSAFE_REAL }; + /* Global visibility options. */ extern struct visibility_flags visibility_options; @@ -738,7 +748,7 @@ extern tree c_common_signed_type (tree); extern tree c_common_signed_or_unsigned_type (int, tree); extern void c_common_init_ts (void); extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int); -extern bool unsafe_conversion_p (tree, tree, bool); +extern enum conversion_safety unsafe_conversion_p (tree, tree, bool); extern bool decl_with_nonnull_addr_p (const_tree); extern tree c_fully_fold (tree, bool, bool *); extern tree decl_constant_value_for_optimization (tree); Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 203640) +++ gcc/c-family/c.opt (working copy) @@ -387,6 +387,10 @@ Werror-implicit-function-declaration C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration) This switch is deprecated; use -Werror=implicit-function-declaration instead +Wfloat-conversion +C ObjC C++ ObjC++ Var(warn_float_conversion) LangEnabledBy(C ObjC C++ ObjC++,Wconversion) +Warn for implicit type conversions that cause loss of floating point precision + Wfloat-equal C ObjC C++ ObjC++ Var(warn_float_equal) Warning Warn if testing floating point numbers for equality Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 203640) +++ gcc/doc/invoke.texi (working copy) @@ -263,7 +263,8 @@ Objective-C and Objective-C++ Dialects}. -Wpointer-arith -Wno-pointer-to-int-cast @gol -Wredundant-decls -Wno-return-local-addr @gol -Wreturn-type -Wsequence-point -Wshadow @gol --Wsign-compare -Wsign-conversion -Wsizeof-pointer-memaccess @gol +-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol +-Wsizeof-pointer-memaccess @gol -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol -Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol @@ -4570,6 +4571,14 @@ value, like assigning a signed integer e integer variable. An explicit cast silences the warning. In C, this option is enabled also by @option{-Wconversion}. +@item -Wfloat-conversion +@opindex Wfloat-conversion +@opindex Wno-float-conversion +Warn for implicit conversions that reduce the precision of a real value. +This includes conversions from real to integer, and from higher precision +real to lower precision real values. This option is also enabled by +@option{-Wconversion}. + @item -Wsizeof-pointer-memaccess @opindex Wsizeof-pointer-memaccess @opindex Wno-sizeof-pointer-memaccess Index: gcc/testsuite/c-c++-common/Wfloat-conversion.c =================================================================== --- gcc/testsuite/c-c++-common/Wfloat-conversion.c (working copy) +++ gcc/testsuite/c-c++-common/Wfloat-conversion.c (working copy) @@ -1,85 +1,58 @@ /* Test for diagnostics for Wconversion for floating-point. */ /* { dg-do compile } */ -/* { dg-skip-if "doubles are floats" { "avr-*-*" } { "*" } { "" } } */ -/* { dg-options "-std=c99 -Wconversion" { target c } } */ -/* { dg-options "-Wconversion" { target c++ } } */ +/* { dg-options "-std=c99 -Wfloat-conversion" { target c } } */ +/* { dg-options "-Wfloat-conversion" { target c++ } } */ /* { dg-require-effective-target large_double } */ +/* { dg-require-effective-target int32plus } */ +/* { dg-require-effective-target double64plus } */ +#include <limits.h> float vfloat; double vdouble; long double vlongdouble; +int bar; +void fsi (signed int x); +void fui (unsigned int x); void ffloat (float f); void fdouble (double d); void flongdouble (long double ld); void h (void) { + unsigned int ui = 3; + int si = 3; + unsigned char uc = 3; + signed char sc = 3; float f = 0; double d = 0; long double ld = 0; - ffloat (3.1); /* { dg-warning "conversion" } */ - vfloat = 3.1; /* { dg-warning "conversion" } */ - ffloat (3.1L); /* { dg-warning "conversion" } */ - vfloat = 3.1L; /* { dg-warning "conversion" } */ - fdouble (3.1L); /* { dg-warning "conversion" "" { target large_long_double } } */ - vdouble = 3.1L; /* { dg-warning "conversion" "" { target large_long_double } } */ - ffloat (vdouble); /* { dg-warning "conversion" } */ - vfloat = vdouble; /* { dg-warning "conversion" } */ - ffloat (vlongdouble); /* { dg-warning "conversion" } */ - vfloat = vlongdouble; /* { dg-warning "conversion" } */ - fdouble (vlongdouble); /* { dg-warning "conversion" "" { target large_long_double } } */ - vdouble = vlongdouble; /* { dg-warning "conversion" "" { target large_long_double } } */ - - - ffloat ((float) 3.1); - vfloat = (float) 3.1; - ffloat ((float) 3.1L); - vfloat = (float) 3.1L; - fdouble ((double) 3.1L); - vdouble = (double) 3.1L; - ffloat ((float) vdouble); - vfloat = (float) vdouble; - ffloat ((float) vlongdouble); - vfloat = (float) vlongdouble; - fdouble ((double) vlongdouble); - vdouble = (double) vlongdouble; - - - ffloat (3.0); - vfloat = 3.0; - ffloat (3.1f); - vfloat = 3.1f; - ffloat (0.25L); - vfloat = 0.25L; - - - fdouble (3.0); - vdouble = 3.0; - fdouble (3.1f); - vdouble = 3.1f; - fdouble (0.25L); - vdouble = 0.25L; - - flongdouble (3.0); - vlongdouble = 3.0; - flongdouble (3.1f); - vlongdouble = 3.1f; - flongdouble (0.25L); - vlongdouble = 0.25L; - - ffloat (f); - vfloat = f; - fdouble (f); - vdouble = f; - fdouble (d); - vdouble = d; - flongdouble (f); - vlongdouble = f; - flongdouble (d); - vlongdouble = d; - flongdouble (ld); - vlongdouble = ld; + ffloat (3.1); /* { dg-warning "float-conversion" } */ + vfloat = 3.1; /* { dg-warning "float-conversion" } */ + ffloat (3.1L); /* { dg-warning "float-conversion" } */ + vfloat = 3.1L; /* { dg-warning "float-conversion" } */ + fdouble (3.1L); /* { dg-warning "float-conversion" "" { target large_long_double } } */ + vdouble = 3.1L; /* { dg-warning "float-conversion" "" { target large_long_double } } */ + ffloat (vdouble); /* { dg-warning "float-conversion" } */ + vfloat = vdouble; /* { dg-warning "float-conversion" } */ + ffloat (vlongdouble); /* { dg-warning "float-conversion" } */ + vfloat = vlongdouble; /* { dg-warning "float-conversion" } */ + fdouble (vlongdouble); /* { dg-warning "float-conversion" "" { target large_long_double } } */ + vdouble = vlongdouble; /* { dg-warning "float-conversion" "" { target large_long_double } } */ + + fsi (3.1f); /* { dg-warning "float-conversion" } */ + si = 3.1f; /* { dg-warning "float-conversion" } */ + fsi (3.1); /* { dg-warning "float-conversion" } */ + si = 3.1; /* { dg-warning "float-conversion" } */ + fsi (d); /* { dg-warning "float-conversion" } */ + si = d; /* { dg-warning "float-conversion" } */ + ffloat (INT_MAX); /* { dg-warning "float-conversion" } */ + vfloat = INT_MAX; /* { dg-warning "float-conversion" } */ + ffloat (16777217); /* { dg-warning "float-conversion" } */ + vfloat = 16777217; /* { dg-warning "float-conversion" } */ + + sc = bar != 0 ? 2.1 : 10; /* { dg-warning "float-conversion" } */ + uc = bar != 0 ? 2.1 : 10; /* { dg-warning "float-conversion" } */ }
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 203640) +++ gcc/c-family/c-common.c (working copy) @@ -2518,7 +2518,7 @@ shorten_binary_op (tree result_type, tre } /* Checks if expression EXPR of real/integer type cannot be converted - to the real/integer type TYPE. Function returns true when: + to the real/integer type TYPE. Function returns non-zero when: * EXPR is a constant which cannot be exactly converted to TYPE * EXPR is not a constant and size of EXPR's type > than size of TYPE, for EXPR type and TYPE being both integers or both real. @@ -2526,12 +2526,12 @@ shorten_binary_op (tree result_type, tre * 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 - does not return true in that case. Function can produce signedness - warnings if PRODUCE_WARNS is true. */ -bool + can return SAFE_CONVERSION (zero) in that case. Function can produce + signedness warnings if PRODUCE_WARNS is true. */ +enum conversion_safety unsafe_conversion_p (tree type, tree expr, bool produce_warns) { - bool give_warning = false; + enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */ tree expr_type = TREE_TYPE (expr); location_t loc = EXPR_LOC_OR_HERE (expr); @@ -2543,7 +2543,7 @@ unsafe_conversion_p (tree type, tree exp && TREE_CODE (type) == INTEGER_TYPE) { if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type))) - give_warning = true; + give_warning = UNSAFE_REAL; } /* Warn for an integer constant that does not fit into integer type. */ else if (TREE_CODE (expr_type) == INTEGER_TYPE @@ -2564,7 +2564,7 @@ unsafe_conversion_p (tree type, tree exp " constant value to negative integer"); } else - give_warning = true; + give_warning = UNSAFE_OTHER; } else if (TREE_CODE (type) == REAL_TYPE) { @@ -2573,7 +2573,7 @@ unsafe_conversion_p (tree type, tree exp { REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) - give_warning = true; + give_warning = UNSAFE_REAL; } /* Warn for a real constant that does not fit into a smaller real type. */ @@ -2582,7 +2582,7 @@ unsafe_conversion_p (tree type, tree exp { REAL_VALUE_TYPE a = TREE_REAL_CST (expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) - give_warning = true; + give_warning = UNSAFE_REAL; } } } @@ -2591,7 +2591,7 @@ unsafe_conversion_p (tree type, tree exp /* Warn for real types converted to integer types. */ if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == INTEGER_TYPE) - give_warning = true; + give_warning = UNSAFE_REAL; else if (TREE_CODE (expr_type) == INTEGER_TYPE && TREE_CODE (type) == INTEGER_TYPE) @@ -2629,7 +2629,7 @@ unsafe_conversion_p (tree type, tree exp && int_fits_type_p (op1, c_common_signed_type (type)) && int_fits_type_p (op1, c_common_unsigned_type (type)))) - return false; + return SAFE_CONVERSION; /* If constant is unsigned and fits in the target type, then the result will also fit. */ else if ((TREE_CODE (op0) == INTEGER_CST @@ -2638,12 +2638,12 @@ unsafe_conversion_p (tree type, tree exp || (TREE_CODE (op1) == INTEGER_CST && unsigned1 && int_fits_type_p (op1, type))) - return false; + return SAFE_CONVERSION; } } /* Warn for integer types converted to smaller integer types. */ if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) - give_warning = true; + give_warning = UNSAFE_OTHER; /* When they are the same width but different signedness, then the value may change. */ @@ -2679,14 +2679,14 @@ unsafe_conversion_p (tree type, tree exp if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound) || !exact_real_truncate (TYPE_MODE (type), &real_high_bound)) - give_warning = true; + give_warning = UNSAFE_OTHER; } /* Warn for real types converted to smaller real types. */ else if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) - give_warning = true; + give_warning = UNSAFE_REAL; } return give_warning; @@ -2700,8 +2700,9 @@ conversion_warning (tree type, tree expr { tree expr_type = TREE_TYPE (expr); location_t loc = EXPR_LOC_OR_HERE (expr); + enum conversion_safety conversion_kind; - if (!warn_conversion && !warn_sign_conversion) + if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion) return; switch (TREE_CODE (expr)) @@ -2728,7 +2729,12 @@ conversion_warning (tree type, tree expr case REAL_CST: case INTEGER_CST: - if (unsafe_conversion_p (type, expr, true)) + conversion_kind = unsafe_conversion_p (type, expr, true); + if (conversion_kind == UNSAFE_REAL) + warning_at (loc, OPT_Wfloat_conversion, + "conversion to %qT alters %qT constant value", + type, expr_type); + else if (conversion_kind) warning_at (loc, OPT_Wconversion, "conversion to %qT alters %qT constant value", type, expr_type); @@ -2747,7 +2753,12 @@ conversion_warning (tree type, tree expr } default: /* 'expr' is not a constant. */ - if (unsafe_conversion_p (type, expr, true)) + conversion_kind = unsafe_conversion_p (type, expr, true); + if (conversion_kind == UNSAFE_REAL) + warning_at (loc, OPT_Wfloat_conversion, + "conversion to %qT from %qT may alter its value", + type, expr_type); + else if (conversion_kind) warning_at (loc, OPT_Wconversion, "conversion to %qT from %qT may alter its value", type, expr_type); Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 203640) +++ gcc/c-family/c-common.h (working copy) @@ -685,6 +685,16 @@ struct visibility_flags unsigned inlines_hidden : 1; /* True when -finlineshidden in effect. */ }; +/* These enumerators are possible types of unsafe conversions. + SAFE_CONVERSION The conversion is safe + UNSAFE_OTHER Another type of conversion with problems + UNSAFE_SIGN Conversion between signed and unsigned integers + which are all warned about immediately, so this is unused + UNSAFE_REAL Conversions that reduce the precision of reals + including conversions from reals to integers + */ +enum conversion_safety { SAFE_CONVERSION = 0, UNSAFE_OTHER, UNSAFE_SIGN, UNSAFE_REAL }; + /* Global visibility options. */ extern struct visibility_flags visibility_options; @@ -738,7 +748,7 @@ extern tree c_common_signed_type (tree); extern tree c_common_signed_or_unsigned_type (int, tree); extern void c_common_init_ts (void); extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int); -extern bool unsafe_conversion_p (tree, tree, bool); +extern enum conversion_safety unsafe_conversion_p (tree, tree, bool); extern bool decl_with_nonnull_addr_p (const_tree); extern tree c_fully_fold (tree, bool, bool *); extern tree decl_constant_value_for_optimization (tree); Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 203640) +++ gcc/c-family/c.opt (working copy) @@ -387,6 +387,10 @@ Werror-implicit-function-declaration C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration) This switch is deprecated; use -Werror=implicit-function-declaration instead +Wfloat-conversion +C ObjC C++ ObjC++ Var(warn_float_conversion) LangEnabledBy(C ObjC C++ ObjC++,Wconversion) +Warn for implicit type conversions that cause loss of floating point precision + Wfloat-equal C ObjC C++ ObjC++ Var(warn_float_equal) Warning Warn if testing floating point numbers for equality Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 203640) +++ gcc/doc/invoke.texi (working copy) @@ -263,7 +263,8 @@ Objective-C and Objective-C++ Dialects}. -Wpointer-arith -Wno-pointer-to-int-cast @gol -Wredundant-decls -Wno-return-local-addr @gol -Wreturn-type -Wsequence-point -Wshadow @gol --Wsign-compare -Wsign-conversion -Wsizeof-pointer-memaccess @gol +-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol +-Wsizeof-pointer-memaccess @gol -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol -Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol @@ -4570,6 +4571,14 @@ value, like assigning a signed integer e integer variable. An explicit cast silences the warning. In C, this option is enabled also by @option{-Wconversion}. +@item -Wfloat-conversion +@opindex Wfloat-conversion +@opindex Wno-float-conversion +Warn for implicit conversions that reduce the precision of a real value. +This includes conversions from real to integer, and from higher precision +real to lower precision real values. This option is also enabled by +@option{-Wconversion}. + @item -Wsizeof-pointer-memaccess @opindex Wsizeof-pointer-memaccess @opindex Wno-sizeof-pointer-memaccess Index: gcc/testsuite/c-c++-common/Wconversion-real.c =================================================================== --- gcc/testsuite/c-c++-common/Wconversion-real.c (revision 203640) +++ gcc/testsuite/c-c++-common/Wconversion-real.c (working copy) @@ -2,8 +2,8 @@ /* { dg-do compile } */ /* { dg-skip-if "doubles are floats" { "avr-*-*" } { "*" } { "" } } */ -/* { dg-options "-std=c99 -Wconversion" { target c } } */ -/* { dg-options "-Wconversion" { target c++ } } */ +/* { dg-options "-std=c99 -Wfloat-conversion" { target c } } */ +/* { dg-options "-Wfloat-conversion" { target c++ } } */ /* { dg-require-effective-target large_double } */ float vfloat; @@ -20,18 +20,18 @@ void h (void) double d = 0; long double ld = 0; - ffloat (3.1); /* { dg-warning "conversion" } */ - vfloat = 3.1; /* { dg-warning "conversion" } */ - ffloat (3.1L); /* { dg-warning "conversion" } */ - vfloat = 3.1L; /* { dg-warning "conversion" } */ - fdouble (3.1L); /* { dg-warning "conversion" "" { target large_long_double } } */ - vdouble = 3.1L; /* { dg-warning "conversion" "" { target large_long_double } } */ - ffloat (vdouble); /* { dg-warning "conversion" } */ - vfloat = vdouble; /* { dg-warning "conversion" } */ - ffloat (vlongdouble); /* { dg-warning "conversion" } */ - vfloat = vlongdouble; /* { dg-warning "conversion" } */ - fdouble (vlongdouble); /* { dg-warning "conversion" "" { target large_long_double } } */ - vdouble = vlongdouble; /* { dg-warning "conversion" "" { target large_long_double } } */ + ffloat (3.1); /* { dg-warning "float-conversion" } */ + vfloat = 3.1; /* { dg-warning "float-conversion" } */ + ffloat (3.1L); /* { dg-warning "float-conversion" } */ + vfloat = 3.1L; /* { dg-warning "float-conversion" } */ + fdouble (3.1L); /* { dg-warning "float-conversion" "" { target large_long_double } } */ + vdouble = 3.1L; /* { dg-warning "float-conversion" "" { target large_long_double } } */ + ffloat (vdouble); /* { dg-warning "float-conversion" } */ + vfloat = vdouble; /* { dg-warning "float-conversion" } */ + ffloat (vlongdouble); /* { dg-warning "float-conversion" } */ + vfloat = vlongdouble; /* { dg-warning "float-conversion" } */ + fdouble (vlongdouble); /* { dg-warning "float-conversion" "" { target large_long_double } } */ + vdouble = vlongdouble; /* { dg-warning "float-conversion" "" { target large_long_double } } */ ffloat ((float) 3.1); Index: gcc/testsuite/gcc.dg/Wconversion-real-integer.c =================================================================== --- gcc/testsuite/gcc.dg/Wconversion-real-integer.c (revision 203640) +++ gcc/testsuite/gcc.dg/Wconversion-real-integer.c (working copy) @@ -25,18 +25,18 @@ void h (void) float f = 3; double d = 3; - fsi (3.1f); /* { dg-warning "conversion" } */ - si = 3.1f; /* { dg-warning "conversion" } */ - fsi (3.1); /* { dg-warning "conversion" } */ - si = 3.1; /* { dg-warning "conversion" } */ - fsi (d); /* { dg-warning "conversion" } */ - si = d; /* { dg-warning "conversion" } */ + fsi (3.1f); /* { dg-warning "float-conversion" } */ + si = 3.1f; /* { dg-warning "float-conversion" } */ + fsi (3.1); /* { dg-warning "float-conversion" } */ + si = 3.1; /* { dg-warning "float-conversion" } */ + fsi (d); /* { dg-warning "float-conversion" } */ + si = d; /* { dg-warning "float-conversion" } */ fui (-1.0); /* { dg-warning "overflow" } */ ui = -1.0; /* { dg-warning "overflow" } */ - ffloat (INT_MAX); /* { dg-warning "conversion" } */ - vfloat = INT_MAX; /* { dg-warning "conversion" } */ - ffloat (16777217); /* { dg-warning "conversion" } */ - vfloat = 16777217; /* { dg-warning "conversion" } */ + ffloat (INT_MAX); /* { dg-warning "float-conversion" } */ + vfloat = INT_MAX; /* { dg-warning "float-conversion" } */ + ffloat (16777217); /* { dg-warning "float-conversion" } */ + vfloat = 16777217; /* { dg-warning "float-conversion" } */ ffloat (si); /* { dg-warning "conversion" } */ vfloat = si; /* { dg-warning "conversion" } */ ffloat (ui); /* { dg-warning "conversion" } */ Index: gcc/testsuite/gcc.dg/pr35635.c =================================================================== --- gcc/testsuite/gcc.dg/pr35635.c (revision 203640) +++ gcc/testsuite/gcc.dg/pr35635.c (working copy) @@ -45,7 +45,7 @@ void func2() /* At least one branch of ? does not fit in the destination, thus warn. */ - schar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion" } */ + schar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "float-conversion" } */ schar_x = bar != 0 ? (signed char) 1024: -1024; /* { dg-warning "conversion" } */ } @@ -61,7 +61,7 @@ void func3() /* At least one branch of ? does not fit in the destination, thus warn. */ - uchar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion" } */ + uchar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "float-conversion" } */ uchar_x = bar != 0 ? (unsigned char) 1024 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
warn_float_patch_and_new_testcase2.diff.sig
Description: PGP signature
warn_float_patch_and_new_testcase.diff.sig
Description: PGP signature
warn_float_patch_simple_trunk.diff.sig
Description: PGP signature