* RFA: PATCH: -Wimplicit-double @ 2010-09-03 16:04 Mark Mitchell 2010-09-03 17:38 ` Mark Mitchell 0 siblings, 1 reply; 12+ messages in thread From: Mark Mitchell @ 2010-09-03 16:04 UTC (permalink / raw) To: joseph; +Cc: gcc-patches This patch implements -Wimplicit-double, a new warning. The goal of the warning is to warn users when a "float" is implicitly converted to a "double". That's useful on a machine with a single-precision FPU; it's easy to write something like: float area(float radius) { return 3.1459 * radius * radius; } and not realize that that you're going to end up with all your math being done in software emulation. This patch implements the warning only for C. Once that functionality has been committed, I will also implement the warning for C++. Tested on arm-none-eabi. OK to apply? -- Mark Mitchell CodeSourcery mark@codesourcery.com (650) 331-3385 x713 2010-09-03 Mark Mitchell <mark@codesourcery.com> * c.opt (Wimplicit-double): New. 2010-09-03 Mark Mitchell <mark@codesourcery.com> * doc/invoke.texi: Document it. * c-typeck.c (convert_arguments): Check for implicit conversions from float to double. (do_warn_implicit_double): New function. (build_conditional_expr): Use it. (build_binary_op): Likewise. 2010-09-03 Mark Mitchell <mark@codesourcery.com> * gcc.dg/Wimplicit-double.c: New. # gcc diff pushd /scratch/mitchell/builds/fsf-mainline/src/gcc-mainline svn diff Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 163782) +++ gcc/doc/invoke.texi (working copy) @@ -241,8 +241,8 @@ Objective-C and Objective-C++ Dialects}. -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral @gol -Wformat-security -Wformat-y2k @gol -Wframe-larger-than=@var{len} -Wjump-misses-init -Wignored-qualifiers @gol --Wimplicit -Wimplicit-function-declaration -Wimplicit-int @gol --Winit-self -Winline @gol +-Wimplicit -Wimplicit-double -Wimplicit-function-declaration @gol +-Wimplicit-int -Winit-self -Winline @gol -Wno-int-to-pointer-cast -Wno-invalid-offsetof @gol -Winvalid-pch -Wlarger-than=@var{len} -Wunsafe-loop-optimizations @gol -Wlogical-op -Wlong-long @gol @@ -3198,6 +3198,30 @@ enabled by default and it is made into a Same as @option{-Wimplicit-int} and @option{-Wimplicit-function-declaration}. This warning is enabled by @option{-Wall}. +@item -Wimplicit-double @r{(C and Objective-C only)} +@opindex Wimplicit-double +@opindex Wno-implicit-double +Give a warning when a value of type @code{float} is implicitly +promoted to @code{double}. CPUs with a 32-bit ``single-precision'' +floating-point unit implement @code{float} in hardware, but emulate +@code{double} in software. On such a machine, doing computations +using @code{double} values is much more expensive because of the +overhead required for software emulation. + +It is easy to accidentally do computations with @code{double} because +floating-point literals are implicitly of type @code{double}. For +example, in: +@smallexample +@group +float area(float radius) +@{ + return 3.14159 * radius * radius; +@} +@end group +@end smallexample +the compiler will perform the entire computation with @code{double} +because the floating-point literal is a @code{double}. + @item -Wignored-qualifiers @r{(C and C++ only)} @opindex Wignored-qualifiers @opindex Wno-ignored-qualifiers Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 163782) +++ gcc/c-family/c.opt (working copy) @@ -266,6 +266,10 @@ Wimplicit C ObjC Var(warn_implicit) Init(-1) Warning Warn about implicit declarations +Wimplicit-double +C ObjC C++ ObjC++ Var(warn_implicit_double) Warning +Warn about implicit conversions from \"float\" to \"double\" + Wimplicit-function-declaration C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning Warn about implicit function declarations Index: gcc/testsuite/gcc.dg/Wimplicit-double.c =================================================================== --- gcc/testsuite/gcc.dg/Wimplicit-double.c (revision 0) +++ gcc/testsuite/gcc.dg/Wimplicit-double.c (revision 0) @@ -0,0 +1,104 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-double" } */ + +#include <stddef.h> + +/* Some targets do not provide <complex.h> so we define I ourselves. */ +#define I 1.0iF +#define ID ((_Complex double)I) + +float f; +double d; +int i; +long double ld; +_Complex float cf; +_Complex double cd; +_Complex long double cld; +size_t s; + +extern void unprototyped_fn (); +extern void varargs_fn (int, ...); +extern void double_fn (double); +extern float float_fn (void); + +void +usual_arithmetic_conversions(void) +{ + float local_f; + _Complex float local_cf; + + /* Values of type "float" are implicitly converted to "double" or + "long double" due to use in arithmetic with "double" or "long + double" operands. */ + local_f = f + 1.0; /* { dg-warning "implicit" } */ + local_f = f - d; /* { dg-warning "implicit" } */ + local_f = 1.0f * 1.0; /* { dg-warning "implicit" } */ + local_f = 1.0f / d; /* { dg-warning "implicit" } */ + + local_cf = cf + 1.0; /* { dg-warning "implicit" } */ + local_cf = cf - d; /* { dg-warning "implicit" } */ + local_cf = cf + 1.0 * ID; /* { dg-warning "implicit" } */ + local_cf = cf - cd; /* { dg-warning "implicit" } */ + + local_f = i ? f : d; /* { dg-warning "implicit" } */ + i = f == d; /* { dg-warning "implicit" } */ + i = d != f; /* { dg-warning "implicit" } */ +} + +void +default_argument_promotion (void) +{ + /* Because there is no prototype, "f" is promoted to "double". */ + unprototyped_fn (f); /* { dg-warning "implicit" } */ + undeclared_fn (f); /* { dg-warning "implicit" } */ + /* Because "f" is part of the variable argument list, it is promoted + to "double". */ + varargs_fn (1, f); /* { dg-warning "implicit" } */ +} + +/* There is no warning when an explicit cast is used to perform the + conversion. */ + +void +casts (void) +{ + float local_f; + _Complex float local_cf; + + local_f = (double)f + 1.0; /* { dg-bogus "implicit" } */ + local_f = (double)f - d; /* { dg-bogus "implicit" } */ + local_f = (double)1.0f + 1.0; /* { dg-bogus "implicit" } */ + local_f = (double)1.0f - d; /* { dg-bogus "implicit" } */ + + local_cf = (_Complex double)cf + 1.0; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf - d; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf + 1.0 * ID; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf - cd; /* { dg-bogus "implicit" } */ + + local_f = i ? (double)f : d; /* { dg-bogus "implicit" } */ + i = (double)f == d; /* { dg-bogus "implicit" } */ + i = d != (double)f; /* { dg-bogus "implicit" } */ +} + +/* There is no warning on conversions that occur in assignment (and + assignment-like) contexts. */ + +void +assignments (void) +{ + d = f; /* { dg-bogus "implicit" } */ + double_fn (f); /* { dg-bogus "implicit" } */ + d = float_fn (); /* { dg-bogus "implicit" } */ +} + +/* There is no warning in non-evaluated contexts. */ + +void +non_evaluated (void) +{ + s = sizeof (f + 1.0); /* { dg-bogus "implicit" } */ + s = __alignof__ (f + 1.0); /* { dg-bogus "implicit" } */ + d = (__typeof__(f + 1.0))f; /* { dg-bogus "implicit" } */ + s = sizeof (i ? f : d); /* { dg-bogus "implicit" } */ + s = sizeof (unprototyped_fn (f)); /* { dg-bogus "implicit" } */ +} Index: gcc/c-typeck.c =================================================================== --- gcc/c-typeck.c (revision 163782) +++ gcc/c-typeck.c (working copy) @@ -3106,8 +3106,15 @@ convert_arguments (tree typelist, VEC(tr if (type_generic) parmval = val; else - /* Convert `float' to `double'. */ - parmval = convert (double_type_node, val); + { + /* Convert `float' to `double'. */ + if (warn_implicit_double && !c_inhibit_evaluation_warnings) + warning (OPT_Wimplicit_double, + "implicit conversion from %qT to %qT when passing " + "argument to function", + valtype, double_type_node); + parmval = convert (double_type_node, val); + } } else if (excess_precision && !type_generic) /* A "double" argument with excess precision being passed @@ -4029,6 +4036,39 @@ ep_convert_and_check (tree type, tree ex return convert (type, expr); } +/* RESULT_TYPE is the result of converting TYPE1 and TYPE2 to a common + type via c_common_type. If -Wimplicit-double is in use, and the + conditions for warning have been met, issue a warning. MSG is the + warning message. It must have two %T specifiers for the type that + was converted (generally "float") and the type to which it was + converted (generally "double), respectively. */ + +static void +do_warn_implicit_double (tree result_type, tree type1, tree type2, + const char *msg) +{ + tree source_type; + + if (!warn_implicit_double) + return; + /* If the conversion will not occur at run-time, there is no need to + warn about it. */ + if (c_inhibit_evaluation_warnings) + return; + if (TYPE_MAIN_VARIANT (result_type) != double_type_node + && TYPE_MAIN_VARIANT (result_type) != complex_double_type_node) + return; + if (TYPE_MAIN_VARIANT (type1) == float_type_node + || TYPE_MAIN_VARIANT (type1) == complex_float_type_node) + source_type = type1; + else if (TYPE_MAIN_VARIANT (type2) == float_type_node + || TYPE_MAIN_VARIANT (type2) == complex_float_type_node) + source_type = type2; + else + return; + warning (OPT_Wimplicit_double, msg, source_type, result_type); +} + /* Build and return a conditional expression IFEXP ? OP1 : OP2. If IFEXP_BCP then the condition is a call to __builtin_constant_p, and if folded to an integer constant then the unselected half may @@ -4140,6 +4180,9 @@ build_conditional_expr (location_t colon || code2 == COMPLEX_TYPE)) { result_type = c_common_type (type1, type2); + do_warn_implicit_double (result_type, type1, type2, + "implicit conversion from %qT to %qT to " + "match other result of conditional"); /* If -Wsign-compare, warn here if type1 and type2 have different signedness. We'll promote the signed to unsigned @@ -9822,6 +9865,10 @@ build_binary_op (location_t location, en if (shorten || common || short_compare) { result_type = c_common_type (type0, type1); + do_warn_implicit_double (result_type, type0, type1, + "implicit conversion from %qT to %qT " + "to match other operand of binary " + "expression"); if (result_type == error_mark_node) return error_mark_node; } popd ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-03 16:04 RFA: PATCH: -Wimplicit-double Mark Mitchell @ 2010-09-03 17:38 ` Mark Mitchell 2010-09-03 17:45 ` Manuel López-Ibáñez 0 siblings, 1 reply; 12+ messages in thread From: Mark Mitchell @ 2010-09-03 17:38 UTC (permalink / raw) To: gcc-patches, Joseph S. Myers [-- Attachment #1: Type: text/plain, Size: 457 bytes --] On 9/3/2010 8:59 AM, Mark Mitchell wrote: > This patch implements -Wimplicit-double, a new warning. The goal of > the warning is to warn users when a "float" is implicitly converted to > a "double". Joseph asked me off-list to make a couple of low-level corrections: (a) Use warning_at where possible (b) Name the parameter to do_warn_implicit_double "gmsgid" for i18n Thanks, -- Mark Mitchell CodeSourcery mark@codesourcery.com (650) 331-3385 x713 [-- Attachment #2: Wimplicit-double.patch --] [-- Type: text/plain, Size: 11651 bytes --] 2010-09-03 Mark Mitchell <mark@codesourcery.com> * c.opt (Wimplicit-double): New. 2010-09-03 Mark Mitchell <mark@codesourcery.com> * doc/invoke.texi: Document it. * c-typeck.c (convert_arguments): Check for implicit conversions from float to double. (do_warn_implicit_double): New function. (build_conditional_expr): Use it. (build_binary_op): Likewise. 2010-09-03 Mark Mitchell <mark@codesourcery.com> * gcc.dg/Wimplicit-double.c: New. # gcc diff pushd /scratch/mitchell/builds/fsf-mainline/src/gcc-mainline svn diff Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 163782) +++ gcc/doc/invoke.texi (working copy) @@ -241,8 +241,8 @@ Objective-C and Objective-C++ Dialects}. -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral @gol -Wformat-security -Wformat-y2k @gol -Wframe-larger-than=@var{len} -Wjump-misses-init -Wignored-qualifiers @gol --Wimplicit -Wimplicit-function-declaration -Wimplicit-int @gol --Winit-self -Winline @gol +-Wimplicit -Wimplicit-double -Wimplicit-function-declaration @gol +-Wimplicit-int -Winit-self -Winline @gol -Wno-int-to-pointer-cast -Wno-invalid-offsetof @gol -Winvalid-pch -Wlarger-than=@var{len} -Wunsafe-loop-optimizations @gol -Wlogical-op -Wlong-long @gol @@ -3198,6 +3198,30 @@ enabled by default and it is made into a Same as @option{-Wimplicit-int} and @option{-Wimplicit-function-declaration}. This warning is enabled by @option{-Wall}. +@item -Wimplicit-double @r{(C and Objective-C only)} +@opindex Wimplicit-double +@opindex Wno-implicit-double +Give a warning when a value of type @code{float} is implicitly +promoted to @code{double}. CPUs with a 32-bit ``single-precision'' +floating-point unit implement @code{float} in hardware, but emulate +@code{double} in software. On such a machine, doing computations +using @code{double} values is much more expensive because of the +overhead required for software emulation. + +It is easy to accidentally do computations with @code{double} because +floating-point literals are implicitly of type @code{double}. For +example, in: +@smallexample +@group +float area(float radius) +@{ + return 3.14159 * radius * radius; +@} +@end group +@end smallexample +the compiler will perform the entire computation with @code{double} +because the floating-point literal is a @code{double}. + @item -Wignored-qualifiers @r{(C and C++ only)} @opindex Wignored-qualifiers @opindex Wno-ignored-qualifiers Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 163782) +++ gcc/c-family/c.opt (working copy) @@ -266,6 +266,10 @@ Wimplicit C ObjC Var(warn_implicit) Init(-1) Warning Warn about implicit declarations +Wimplicit-double +C ObjC C++ ObjC++ Var(warn_implicit_double) Warning +Warn about implicit conversions from \"float\" to \"double\" + Wimplicit-function-declaration C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning Warn about implicit function declarations Index: gcc/c-family/ChangeLog =================================================================== --- gcc/c-family/ChangeLog (revision 163782) +++ gcc/c-family/ChangeLog (working copy) @@ -1,3 +1,7 @@ +2010-09-03 Mark Mitchell <mark@codesourcery.com> + + * c.opt (Wimplicit-double): New. + 2010-09-02 Joseph Myers <joseph@codesourcery.com> * c.opt (Wimport, fall-virtual, falt-external-templates, Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 163782) +++ gcc/ChangeLog (working copy) @@ -1,3 +1,12 @@ +2010-09-03 Mark Mitchell <mark@codesourcery.com> + + * doc/invoke.texi: Document it. + * c-typeck.c (convert_arguments): Check for implicit conversions + from float to double. + (do_warn_implicit_double): New function. + (build_conditional_expr): Use it. + (build_binary_op): Likewise. + 2010-09-02 Ryan Mansfield <rmansfield@qnx.com> * arm.c (arm_override_options): Correct fall-back code to use Index: gcc/testsuite/gcc.dg/Wimplicit-double.c =================================================================== --- gcc/testsuite/gcc.dg/Wimplicit-double.c (revision 0) +++ gcc/testsuite/gcc.dg/Wimplicit-double.c (revision 0) @@ -0,0 +1,104 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-double" } */ + +#include <stddef.h> + +/* Some targets do not provide <complex.h> so we define I ourselves. */ +#define I 1.0iF +#define ID ((_Complex double)I) + +float f; +double d; +int i; +long double ld; +_Complex float cf; +_Complex double cd; +_Complex long double cld; +size_t s; + +extern void unprototyped_fn (); +extern void varargs_fn (int, ...); +extern void double_fn (double); +extern float float_fn (void); + +void +usual_arithmetic_conversions(void) +{ + float local_f; + _Complex float local_cf; + + /* Values of type "float" are implicitly converted to "double" or + "long double" due to use in arithmetic with "double" or "long + double" operands. */ + local_f = f + 1.0; /* { dg-warning "implicit" } */ + local_f = f - d; /* { dg-warning "implicit" } */ + local_f = 1.0f * 1.0; /* { dg-warning "implicit" } */ + local_f = 1.0f / d; /* { dg-warning "implicit" } */ + + local_cf = cf + 1.0; /* { dg-warning "implicit" } */ + local_cf = cf - d; /* { dg-warning "implicit" } */ + local_cf = cf + 1.0 * ID; /* { dg-warning "implicit" } */ + local_cf = cf - cd; /* { dg-warning "implicit" } */ + + local_f = i ? f : d; /* { dg-warning "implicit" } */ + i = f == d; /* { dg-warning "implicit" } */ + i = d != f; /* { dg-warning "implicit" } */ +} + +void +default_argument_promotion (void) +{ + /* Because there is no prototype, "f" is promoted to "double". */ + unprototyped_fn (f); /* { dg-warning "implicit" } */ + undeclared_fn (f); /* { dg-warning "implicit" } */ + /* Because "f" is part of the variable argument list, it is promoted + to "double". */ + varargs_fn (1, f); /* { dg-warning "implicit" } */ +} + +/* There is no warning when an explicit cast is used to perform the + conversion. */ + +void +casts (void) +{ + float local_f; + _Complex float local_cf; + + local_f = (double)f + 1.0; /* { dg-bogus "implicit" } */ + local_f = (double)f - d; /* { dg-bogus "implicit" } */ + local_f = (double)1.0f + 1.0; /* { dg-bogus "implicit" } */ + local_f = (double)1.0f - d; /* { dg-bogus "implicit" } */ + + local_cf = (_Complex double)cf + 1.0; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf - d; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf + 1.0 * ID; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf - cd; /* { dg-bogus "implicit" } */ + + local_f = i ? (double)f : d; /* { dg-bogus "implicit" } */ + i = (double)f == d; /* { dg-bogus "implicit" } */ + i = d != (double)f; /* { dg-bogus "implicit" } */ +} + +/* There is no warning on conversions that occur in assignment (and + assignment-like) contexts. */ + +void +assignments (void) +{ + d = f; /* { dg-bogus "implicit" } */ + double_fn (f); /* { dg-bogus "implicit" } */ + d = float_fn (); /* { dg-bogus "implicit" } */ +} + +/* There is no warning in non-evaluated contexts. */ + +void +non_evaluated (void) +{ + s = sizeof (f + 1.0); /* { dg-bogus "implicit" } */ + s = __alignof__ (f + 1.0); /* { dg-bogus "implicit" } */ + d = (__typeof__(f + 1.0))f; /* { dg-bogus "implicit" } */ + s = sizeof (i ? f : d); /* { dg-bogus "implicit" } */ + s = sizeof (unprototyped_fn (f)); /* { dg-bogus "implicit" } */ +} Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 163782) +++ gcc/testsuite/ChangeLog (working copy) @@ -1,3 +1,7 @@ +2010-09-03 Mark Mitchell <mark@codesourcery.com> + + * gcc.dg/Wimplicit-double.c: New. + 2010-09-02 Eric Botcazou <ebotcazou@adacore.com> * g++.dg/debug/dwarf2/nested-2.C: Allow for ! as comment delimiter. Index: gcc/c-typeck.c =================================================================== --- gcc/c-typeck.c (revision 163782) +++ gcc/c-typeck.c (working copy) @@ -3106,8 +3106,15 @@ convert_arguments (tree typelist, VEC(tr if (type_generic) parmval = val; else - /* Convert `float' to `double'. */ - parmval = convert (double_type_node, val); + { + /* Convert `float' to `double'. */ + if (warn_implicit_double && !c_inhibit_evaluation_warnings) + warning (OPT_Wimplicit_double, + "implicit conversion from %qT to %qT when passing " + "argument to function", + valtype, double_type_node); + parmval = convert (double_type_node, val); + } } else if (excess_precision && !type_generic) /* A "double" argument with excess precision being passed @@ -4029,6 +4036,40 @@ ep_convert_and_check (tree type, tree ex return convert (type, expr); } +/* RESULT_TYPE is the result of converting TYPE1 and TYPE2 to a common + type via c_common_type. If -Wimplicit-double is in use, and the + conditions for warning have been met, issue a warning. GMSGID is + the warning message. It must have two %T specifiers for the type + that was converted (generally "float") and the type to which it was + converted (generally "double), respectively. LOC is the location + to which the awrning should refer. */ + +static void +do_warn_implicit_double (tree result_type, tree type1, tree type2, + const char *gmsgid, location_t loc) +{ + tree source_type; + + if (!warn_implicit_double) + return; + /* If the conversion will not occur at run-time, there is no need to + warn about it. */ + if (c_inhibit_evaluation_warnings) + return; + if (TYPE_MAIN_VARIANT (result_type) != double_type_node + && TYPE_MAIN_VARIANT (result_type) != complex_double_type_node) + return; + if (TYPE_MAIN_VARIANT (type1) == float_type_node + || TYPE_MAIN_VARIANT (type1) == complex_float_type_node) + source_type = type1; + else if (TYPE_MAIN_VARIANT (type2) == float_type_node + || TYPE_MAIN_VARIANT (type2) == complex_float_type_node) + source_type = type2; + else + return; + warning_at (loc, OPT_Wimplicit_double, gmsgid, source_type, result_type); +} + /* Build and return a conditional expression IFEXP ? OP1 : OP2. If IFEXP_BCP then the condition is a call to __builtin_constant_p, and if folded to an integer constant then the unselected half may @@ -4140,6 +4181,10 @@ build_conditional_expr (location_t colon || code2 == COMPLEX_TYPE)) { result_type = c_common_type (type1, type2); + do_warn_implicit_double (result_type, type1, type2, + "implicit conversion from %qT to %qT to " + "match other result of conditional", + colon_loc); /* If -Wsign-compare, warn here if type1 and type2 have different signedness. We'll promote the signed to unsigned @@ -9822,6 +9867,11 @@ build_binary_op (location_t location, en if (shorten || common || short_compare) { result_type = c_common_type (type0, type1); + do_warn_implicit_double (result_type, type0, type1, + "implicit conversion from %qT to %qT " + "to match other operand of binary " + "expression", + location); if (result_type == error_mark_node) return error_mark_node; } popd ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-03 17:38 ` Mark Mitchell @ 2010-09-03 17:45 ` Manuel López-Ibáñez 2010-09-03 17:51 ` Manuel López-Ibáñez 2010-09-03 18:06 ` Mark Mitchell 0 siblings, 2 replies; 12+ messages in thread From: Manuel López-Ibáñez @ 2010-09-03 17:45 UTC (permalink / raw) To: Mark Mitchell; +Cc: gcc-patches, Joseph S. Myers On 3 September 2010 19:18, Mark Mitchell <mark@codesourcery.com> wrote: > On 9/3/2010 8:59 AM, Mark Mitchell wrote: > >> This patch implements -Wimplicit-double, a new warning. The goal of >> the warning is to warn users when a "float" is implicitly converted to >> a "double". > > Joseph asked me off-list to make a couple of low-level corrections: > > (a) Use warning_at where possible > (b) Name the parameter to do_warn_implicit_double "gmsgid" for i18n > > Thanks, This is warned already by Wconversion for both C and C++ and Fortran! If it doesn't catch all cases, then that should be fixed appropriately to use existing code as much as possible. And there are testcases already for this in the testsuite. The name of the option suggests that existing Wimplicit-int should do something similar for integers, which is not the case at all. So bad name. I suggest Wconversion-double or Wdouble-conversion and make this option enabled by Wconversion similar to existing option Wnull-conversion. So I think this patch is not OK at all. Cheers, Manuel. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-03 17:45 ` Manuel López-Ibáñez @ 2010-09-03 17:51 ` Manuel López-Ibáñez 2010-09-03 18:06 ` Mark Mitchell 1 sibling, 0 replies; 12+ messages in thread From: Manuel López-Ibáñez @ 2010-09-03 17:51 UTC (permalink / raw) To: Mark Mitchell; +Cc: gcc-patches, Joseph S. Myers On 3 September 2010 19:43, Manuel López-Ibáñez <lopezibanez@gmail.com> wrote: > On 3 September 2010 19:18, Mark Mitchell <mark@codesourcery.com> wrote: >> On 9/3/2010 8:59 AM, Mark Mitchell wrote: >> >>> This patch implements -Wimplicit-double, a new warning. The goal of >>> the warning is to warn users when a "float" is implicitly converted to >>> a "double". >> >> Joseph asked me off-list to make a couple of low-level corrections: >> >> (a) Use warning_at where possible >> (b) Name the parameter to do_warn_implicit_double "gmsgid" for i18n >> >> Thanks, > > This is warned already by Wconversion for both C and C++ and Fortran! > If it doesn't catch all cases, then that should be fixed appropriately > to use existing code as much as possible. And there are testcases > already for this in the testsuite. In fact, the case without prototype is different and is warned by Wtraditional-conversion. There are also testcases in the testsuite. So that part seems to be also duplicated. Cheers, Manuel. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-03 17:45 ` Manuel López-Ibáñez 2010-09-03 17:51 ` Manuel López-Ibáñez @ 2010-09-03 18:06 ` Mark Mitchell 2010-09-03 19:03 ` Manuel López-Ibáñez 1 sibling, 1 reply; 12+ messages in thread From: Mark Mitchell @ 2010-09-03 18:06 UTC (permalink / raw) To: Manuel López-Ibáñez; +Cc: gcc-patches, Joseph S. Myers On 9/3/2010 10:43 AM, Manuel López-Ibáñez wrote: >>> This patch implements -Wimplicit-double, a new warning. The goal of >>> the warning is to warn users when a "float" is implicitly converted to >>> a "double". > This is warned already by Wconversion for both C and C++ and Fortran! The fact that there's another warning option which warns about the same code is irrelevant. -Wconversion and -Wtraditional-conversion are warning about something entirely different, from the user's perspective. For example, -Wconversion warns about conversions that alter a value. That's not the point here; this is about a value being altered, it's about using a type that your hardware doesn't support natively. It's entirely possible that a user doesn't want all the warnings that would come from -Wconversion or -Wtraditional-conversion, but does want this class of warnings. -- Mark Mitchell CodeSourcery mark@codesourcery.com (650) 331-3385 x713 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-03 18:06 ` Mark Mitchell @ 2010-09-03 19:03 ` Manuel López-Ibáñez 2010-09-03 19:13 ` Mark Mitchell 0 siblings, 1 reply; 12+ messages in thread From: Manuel López-Ibáñez @ 2010-09-03 19:03 UTC (permalink / raw) To: Mark Mitchell; +Cc: gcc-patches, Joseph S. Myers On 3 September 2010 19:51, Mark Mitchell <mark@codesourcery.com> wrote: > For example, -Wconversion warns about conversions that alter a value. > That's not the point here; this is about a value being altered, it's > about using a type that your hardware doesn't support natively. It's Fine. I didn't realise it was a conversion from float->double. I see the point of the warning now. Still, Wimplicit-double is a bad name given the existing Wimplicit and Wimplicit-int. It could be Wpromoted-double or Wpromoted-to-double or something that cannot be confused with Wconversion or Wimplicit. Cheers, Manuel. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-03 19:03 ` Manuel López-Ibáñez @ 2010-09-03 19:13 ` Mark Mitchell 2010-09-04 8:35 ` Daniel Jacobowitz 0 siblings, 1 reply; 12+ messages in thread From: Mark Mitchell @ 2010-09-03 19:13 UTC (permalink / raw) To: Manuel López-Ibáñez; +Cc: gcc-patches, Joseph S. Myers On 9/3/2010 11:36 AM, Manuel López-Ibáñez wrote: > On 3 September 2010 19:51, Mark Mitchell <mark@codesourcery.com> wrote: >> For example, -Wconversion warns about conversions that alter a value. >> That's not the point here; this is about a value being altered, it's >> about using a type that your hardware doesn't support natively. It's > > Fine. I didn't realise it was a conversion from float->double. I see > the point of the warning now. Still, Wimplicit-double is a bad name I don't have a strong feeling about the name. -Wpromoted-double sounds like promotion *from* double, and -Wpromoted-to-double is pretty ungainly. But, that's a bikeshed. If the patch as a whole is approved, I'll accept whatever name someone wants to put on it. -- Mark Mitchell CodeSourcery mark@codesourcery.com (650) 331-3385 x713 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-03 19:13 ` Mark Mitchell @ 2010-09-04 8:35 ` Daniel Jacobowitz 2010-09-04 12:47 ` Gabriel Dos Reis 0 siblings, 1 reply; 12+ messages in thread From: Daniel Jacobowitz @ 2010-09-04 8:35 UTC (permalink / raw) To: Mark Mitchell Cc: Manuel López-Ibáñez, gcc-patches, Joseph S. Myers On Fri, Sep 03, 2010 at 11:41:24AM -0700, Mark Mitchell wrote: > On 9/3/2010 11:36 AM, Manuel López-Ibáñez wrote: > > On 3 September 2010 19:51, Mark Mitchell <mark@codesourcery.com> wrote: > >> For example, -Wconversion warns about conversions that alter a value. > >> That's not the point here; this is about a value being altered, it's > >> about using a type that your hardware doesn't support natively. It's > > > > Fine. I didn't realise it was a conversion from float->double. I see > > the point of the warning now. Still, Wimplicit-double is a bad name > > I don't have a strong feeling about the name. -Wpromoted-double sounds > like promotion *from* double, and -Wpromoted-to-double is pretty > ungainly. But, that's a bikeshed. > > If the patch as a whole is approved, I'll accept whatever name someone > wants to put on it. It's not much better, but that argument suggests -Wdouble-promotion. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-04 8:35 ` Daniel Jacobowitz @ 2010-09-04 12:47 ` Gabriel Dos Reis 2010-09-05 22:15 ` Mark Mitchell 0 siblings, 1 reply; 12+ messages in thread From: Gabriel Dos Reis @ 2010-09-04 12:47 UTC (permalink / raw) To: Mark Mitchell, Manuel López-Ibáñez, gcc-patches, Joseph S. Myers On Fri, Sep 3, 2010 at 8:44 PM, Daniel Jacobowitz <dan@codesourcery.com> wrote: > > It's not much better, but that argument suggests -Wdouble-promotion. I agree that -Wdouble-promotion is better than -Wimplicit-double. Patch OK with me. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-04 12:47 ` Gabriel Dos Reis @ 2010-09-05 22:15 ` Mark Mitchell 2010-09-06 17:57 ` Mark Mitchell 0 siblings, 1 reply; 12+ messages in thread From: Mark Mitchell @ 2010-09-05 22:15 UTC (permalink / raw) To: Gabriel Dos Reis Cc: Manuel López-Ibáñez, gcc-patches, Joseph S. Myers [-- Attachment #1: Type: text/plain, Size: 309 bytes --] On 9/4/2010 4:54 AM, Gabriel Dos Reis wrote: > I agree that -Wdouble-promotion is better than -Wimplicit-double. > Patch OK with me. OK, here's the version I checked in. I will now implement the C++ version of the warning. Thanks, -- Mark Mitchell CodeSourcery mark@codesourcery.com (650) 331-3385 x713 [-- Attachment #2: Wdouble-promotion.patch --] [-- Type: text/plain, Size: 10068 bytes --] 2010-09-05 Mark Mitchell <mark@codesourcery.com> * c.opt (Wdouble-promotion): New. 2010-09-05 Mark Mitchell <mark@codesourcery.com> * doc/invoke.texi: Document -Wdouble-promotion. * c-typeck.c (convert_arguments): Check for implicit conversions from float to double. (do_warn_double_promotion): New function. (build_conditional_expr): Use it. (build_binary_op): Likewise. 2010-09-05 Mark Mitchell <mark@codesourcery.com> * gcc.dg/Wdouble-promotion.c: New. Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 163883) +++ gcc/doc/invoke.texi (working copy) @@ -235,8 +235,8 @@ Objective-C and Objective-C++ Dialects}. -Wchar-subscripts -Wclobbered -Wcomment @gol -Wconversion -Wcoverage-mismatch -Wcpp -Wno-deprecated @gol -Wno-deprecated-declarations -Wdisabled-optimization @gol --Wno-div-by-zero -Wempty-body -Wenum-compare -Wno-endif-labels @gol --Werror -Werror=* @gol +-Wno-div-by-zero -Wdouble-promotion -Wempty-body -Wenum-compare @gol +-Wno-endif-labels -Werror -Werror=* @gol -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral @gol -Wformat-security -Wformat-y2k @gol @@ -3053,6 +3053,30 @@ This warning is enabled by @option{-Wall Suppress warning messages emitted by @code{#warning} directives. +@item -Wdouble-promotion @r{(C and Objective-C only)} +@opindex Wdouble-promotion +@opindex Wno-double-promotion +Give a warning when a value of type @code{float} is implicitly +promoted to @code{double}. CPUs with a 32-bit ``single-precision'' +floating-point unit implement @code{float} in hardware, but emulate +@code{double} in software. On such a machine, doing computations +using @code{double} values is much more expensive because of the +overhead required for software emulation. + +It is easy to accidentally do computations with @code{double} because +floating-point literals are implicitly of type @code{double}. For +example, in: +@smallexample +@group +float area(float radius) +@{ + return 3.14159 * radius * radius; +@} +@end group +@end smallexample +the compiler will perform the entire computation with @code{double} +because the floating-point literal is a @code{double}. + @item -Wformat @opindex Wformat @opindex Wno-format Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 163883) +++ gcc/c-family/c.opt (working copy) @@ -266,6 +266,10 @@ Wimplicit C ObjC Var(warn_implicit) Init(-1) Warning Warn about implicit declarations +Wdouble-promotion +C ObjC C++ ObjC++ Var(warn_double_promotion) Warning +Warn about implicit conversions from \"float\" to \"double\" + Wimplicit-function-declaration C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning Warn about implicit function declarations Index: gcc/testsuite/gcc.dg/Wdouble-promotion.c =================================================================== --- gcc/testsuite/gcc.dg/Wdouble-promotion.c (revision 0) +++ gcc/testsuite/gcc.dg/Wdouble-promotion.c (revision 0) @@ -0,0 +1,104 @@ +/* { dg-do compile } */ +/* { dg-options "-Wdouble-promotion" } */ + +#include <stddef.h> + +/* Some targets do not provide <complex.h> so we define I ourselves. */ +#define I 1.0iF +#define ID ((_Complex double)I) + +float f; +double d; +int i; +long double ld; +_Complex float cf; +_Complex double cd; +_Complex long double cld; +size_t s; + +extern void unprototyped_fn (); +extern void varargs_fn (int, ...); +extern void double_fn (double); +extern float float_fn (void); + +void +usual_arithmetic_conversions(void) +{ + float local_f; + _Complex float local_cf; + + /* Values of type "float" are implicitly converted to "double" or + "long double" due to use in arithmetic with "double" or "long + double" operands. */ + local_f = f + 1.0; /* { dg-warning "implicit" } */ + local_f = f - d; /* { dg-warning "implicit" } */ + local_f = 1.0f * 1.0; /* { dg-warning "implicit" } */ + local_f = 1.0f / d; /* { dg-warning "implicit" } */ + + local_cf = cf + 1.0; /* { dg-warning "implicit" } */ + local_cf = cf - d; /* { dg-warning "implicit" } */ + local_cf = cf + 1.0 * ID; /* { dg-warning "implicit" } */ + local_cf = cf - cd; /* { dg-warning "implicit" } */ + + local_f = i ? f : d; /* { dg-warning "implicit" } */ + i = f == d; /* { dg-warning "implicit" } */ + i = d != f; /* { dg-warning "implicit" } */ +} + +void +default_argument_promotion (void) +{ + /* Because there is no prototype, "f" is promoted to "double". */ + unprototyped_fn (f); /* { dg-warning "implicit" } */ + undeclared_fn (f); /* { dg-warning "implicit" } */ + /* Because "f" is part of the variable argument list, it is promoted + to "double". */ + varargs_fn (1, f); /* { dg-warning "implicit" } */ +} + +/* There is no warning when an explicit cast is used to perform the + conversion. */ + +void +casts (void) +{ + float local_f; + _Complex float local_cf; + + local_f = (double)f + 1.0; /* { dg-bogus "implicit" } */ + local_f = (double)f - d; /* { dg-bogus "implicit" } */ + local_f = (double)1.0f + 1.0; /* { dg-bogus "implicit" } */ + local_f = (double)1.0f - d; /* { dg-bogus "implicit" } */ + + local_cf = (_Complex double)cf + 1.0; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf - d; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf + 1.0 * ID; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf - cd; /* { dg-bogus "implicit" } */ + + local_f = i ? (double)f : d; /* { dg-bogus "implicit" } */ + i = (double)f == d; /* { dg-bogus "implicit" } */ + i = d != (double)f; /* { dg-bogus "implicit" } */ +} + +/* There is no warning on conversions that occur in assignment (and + assignment-like) contexts. */ + +void +assignments (void) +{ + d = f; /* { dg-bogus "implicit" } */ + double_fn (f); /* { dg-bogus "implicit" } */ + d = float_fn (); /* { dg-bogus "implicit" } */ +} + +/* There is no warning in non-evaluated contexts. */ + +void +non_evaluated (void) +{ + s = sizeof (f + 1.0); /* { dg-bogus "implicit" } */ + s = __alignof__ (f + 1.0); /* { dg-bogus "implicit" } */ + d = (__typeof__(f + 1.0))f; /* { dg-bogus "implicit" } */ + s = sizeof (i ? f : d); /* { dg-bogus "implicit" } */ + s = sizeof (unprototyped_fn (f)); /* { dg-bogus "implicit" } */ +} Index: gcc/c-typeck.c =================================================================== --- gcc/c-typeck.c (revision 163883) +++ gcc/c-typeck.c (working copy) @@ -3106,8 +3106,15 @@ convert_arguments (tree typelist, VEC(tr if (type_generic) parmval = val; else - /* Convert `float' to `double'. */ - parmval = convert (double_type_node, val); + { + /* Convert `float' to `double'. */ + if (warn_double_promotion && !c_inhibit_evaluation_warnings) + warning (OPT_Wdouble_promotion, + "implicit conversion from %qT to %qT when passing " + "argument to function", + valtype, double_type_node); + parmval = convert (double_type_node, val); + } } else if (excess_precision && !type_generic) /* A "double" argument with excess precision being passed @@ -4029,6 +4036,40 @@ ep_convert_and_check (tree type, tree ex return convert (type, expr); } +/* RESULT_TYPE is the result of converting TYPE1 and TYPE2 to a common + type via c_common_type. If -Wdouble-promotion is in use, and the + conditions for warning have been met, issue a warning. GMSGID is + the warning message. It must have two %T specifiers for the type + that was converted (generally "float") and the type to which it was + converted (generally "double), respectively. LOC is the location + to which the awrning should refer. */ + +static void +do_warn_double_promotion (tree result_type, tree type1, tree type2, + const char *gmsgid, location_t loc) +{ + tree source_type; + + if (!warn_double_promotion) + return; + /* If the conversion will not occur at run-time, there is no need to + warn about it. */ + if (c_inhibit_evaluation_warnings) + return; + if (TYPE_MAIN_VARIANT (result_type) != double_type_node + && TYPE_MAIN_VARIANT (result_type) != complex_double_type_node) + return; + if (TYPE_MAIN_VARIANT (type1) == float_type_node + || TYPE_MAIN_VARIANT (type1) == complex_float_type_node) + source_type = type1; + else if (TYPE_MAIN_VARIANT (type2) == float_type_node + || TYPE_MAIN_VARIANT (type2) == complex_float_type_node) + source_type = type2; + else + return; + warning_at (loc, OPT_Wdouble_promotion, gmsgid, source_type, result_type); +} + /* Build and return a conditional expression IFEXP ? OP1 : OP2. If IFEXP_BCP then the condition is a call to __builtin_constant_p, and if folded to an integer constant then the unselected half may @@ -4140,6 +4181,10 @@ build_conditional_expr (location_t colon || code2 == COMPLEX_TYPE)) { result_type = c_common_type (type1, type2); + do_warn_double_promotion (result_type, type1, type2, + "implicit conversion from %qT to %qT to " + "match other result of conditional", + colon_loc); /* If -Wsign-compare, warn here if type1 and type2 have different signedness. We'll promote the signed to unsigned @@ -9822,6 +9867,11 @@ build_binary_op (location_t location, en if (shorten || common || short_compare) { result_type = c_common_type (type0, type1); + do_warn_double_promotion (result_type, type0, type1, + "implicit conversion from %qT to %qT " + "to match other operand of binary " + "expression", + location); if (result_type == error_mark_node) return error_mark_node; } ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: RFA: PATCH: -Wimplicit-double 2010-09-05 22:15 ` Mark Mitchell @ 2010-09-06 17:57 ` Mark Mitchell 2010-10-17 16:36 ` [wwwdocs] PATCH for -Wimplicit-double Gerald Pfeifer 0 siblings, 1 reply; 12+ messages in thread From: Mark Mitchell @ 2010-09-06 17:57 UTC (permalink / raw) To: gcc-patches [-- Attachment #1: Type: text/plain, Size: 247 bytes --] On 9/5/2010 2:54 PM, Mark Mitchell wrote: > OK, here's the version I checked in. I will now implement the C++ > version of the warning. Here's the C++ patch. Committed. -- Mark Mitchell CodeSourcery mark@codesourcery.com (650) 331-3385 x713 [-- Attachment #2: Wdouble-promotion.patch --] [-- Type: text/plain, Size: 12870 bytes --] 2010-09-06 Mark Mitchell <mark@codesourcery.com> * c-common.h (do_warn_double_promotion): Declare. * c-common.c (do_warn_double_promotion): Define. 2010-09-06 Mark Mitchell <mark@codesourcery.com> * c-typeck.c (do_warn_double_promotion): Remove. * doc/invoke.texi (-Wdouble-promotion): Note available for C++ and Objective-C++ too. 2010-09-06 Mark Mitchell <mark@codesourcery.com> * typeck.c (cp_build_binary_op): Call do_warn_double_promotion. * call.c (build_conditional_expr): Likewise. (convert_arg_to_ellipsis): Likewise. 2010-09-06 Mark Mitchell <mark@codesourcery.com> * g++.dg/warn/Wdouble-promotion.C: New. # gcc diff pushd /scratch/mitchell/builds/fsf-mainline/src/gcc-mainline svn diff Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 163924) +++ gcc/doc/invoke.texi (working copy) @@ -3053,7 +3053,7 @@ This warning is enabled by @option{-Wall Suppress warning messages emitted by @code{#warning} directives. -@item -Wdouble-promotion @r{(C and Objective-C only)} +@item -Wdouble-promotion @r{(C, C++, Objective-C and Objective-C++ only)} @opindex Wdouble-promotion @opindex Wno-double-promotion Give a warning when a value of type @code{float} is implicitly Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 163924) +++ gcc/c-family/c-common.c (working copy) @@ -9128,6 +9128,40 @@ warn_for_sign_compare (location_t locati } } +/* RESULT_TYPE is the result of converting TYPE1 and TYPE2 to a common + type via c_common_type. If -Wdouble-promotion is in use, and the + conditions for warning have been met, issue a warning. GMSGID is + the warning message. It must have two %T specifiers for the type + that was converted (generally "float") and the type to which it was + converted (generally "double), respectively. LOC is the location + to which the awrning should refer. */ + +void +do_warn_double_promotion (tree result_type, tree type1, tree type2, + const char *gmsgid, location_t loc) +{ + tree source_type; + + if (!warn_double_promotion) + return; + /* If the conversion will not occur at run-time, there is no need to + warn about it. */ + if (c_inhibit_evaluation_warnings) + return; + if (TYPE_MAIN_VARIANT (result_type) != double_type_node + && TYPE_MAIN_VARIANT (result_type) != complex_double_type_node) + return; + if (TYPE_MAIN_VARIANT (type1) == float_type_node + || TYPE_MAIN_VARIANT (type1) == complex_float_type_node) + source_type = type1; + else if (TYPE_MAIN_VARIANT (type2) == float_type_node + || TYPE_MAIN_VARIANT (type2) == complex_float_type_node) + source_type = type2; + else + return; + warning_at (loc, OPT_Wdouble_promotion, gmsgid, source_type, result_type); +} + /* Setup a TYPE_DECL node as a typedef representation. X is a TYPE_DECL for a typedef statement. Create a brand new Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 163924) +++ gcc/c-family/c-common.h (working copy) @@ -900,6 +900,8 @@ extern void warn_for_sign_compare (locat tree op0, tree op1, tree result_type, enum tree_code resultcode); +extern void do_warn_double_promotion (tree, tree, tree, const char *, + location_t); extern void set_underlying_type (tree x); extern VEC(tree,gc) *make_tree_vector (void); extern void release_tree_vector (VEC(tree,gc) *); Index: gcc/testsuite/g++.dg/warn/Wdouble-promotion.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wdouble-promotion.C (revision 0) +++ gcc/testsuite/g++.dg/warn/Wdouble-promotion.C (revision 0) @@ -0,0 +1,99 @@ +/* { dg-do compile } */ +/* { dg-options "-Wdouble-promotion" } */ + +#include <stddef.h> + +/* Some targets do not provide <complex.h> so we define I ourselves. */ +#define I 1.0iF +#define ID ((_Complex double)I) + +float f; +double d; +int i; +long double ld; +_Complex float cf; +_Complex double cd; +_Complex long double cld; +size_t s; + +extern void varargs_fn (int, ...); +extern void double_fn (double); +extern float float_fn (void); + +void +usual_arithmetic_conversions(void) +{ + float local_f; + _Complex float local_cf; + + /* Values of type "float" are implicitly converted to "double" or + "long double" due to use in arithmetic with "double" or "long + double" operands. */ + local_f = f + 1.0; /* { dg-warning "implicit" } */ + local_f = f - d; /* { dg-warning "implicit" } */ + local_f = 1.0f * 1.0; /* { dg-warning "implicit" } */ + local_f = 1.0f / d; /* { dg-warning "implicit" } */ + + local_cf = cf + 1.0; /* { dg-warning "implicit" } */ + local_cf = cf - d; /* { dg-warning "implicit" } */ + local_cf = cf + 1.0 * ID; /* { dg-warning "implicit" } */ + local_cf = cf - cd; /* { dg-warning "implicit" } */ + + local_f = i ? f : d; /* { dg-warning "implicit" } */ + i = f == d; /* { dg-warning "implicit" } */ + i = d != f; /* { dg-warning "implicit" } */ +} + +void +default_argument_promotion (void) +{ + /* Because "f" is part of the variable argument list, it is promoted + to "double". */ + varargs_fn (1, f); /* { dg-warning "implicit" } */ +} + +/* There is no warning when an explicit cast is used to perform the + conversion. */ + +void +casts (void) +{ + float local_f; + _Complex float local_cf; + + local_f = (double)f + 1.0; /* { dg-bogus "implicit" } */ + local_f = (double)f - d; /* { dg-bogus "implicit" } */ + local_f = (double)1.0f + 1.0; /* { dg-bogus "implicit" } */ + local_f = (double)1.0f - d; /* { dg-bogus "implicit" } */ + + local_cf = (_Complex double)cf + 1.0; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf - d; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf + 1.0 * ID; /* { dg-bogus "implicit" } */ + local_cf = (_Complex double)cf - cd; /* { dg-bogus "implicit" } */ + + local_f = i ? (double)f : d; /* { dg-bogus "implicit" } */ + i = (double)f == d; /* { dg-bogus "implicit" } */ + i = d != (double)f; /* { dg-bogus "implicit" } */ +} + +/* There is no warning on conversions that occur in assignment (and + assignment-like) contexts. */ + +void +assignments (void) +{ + d = f; /* { dg-bogus "implicit" } */ + double_fn (f); /* { dg-bogus "implicit" } */ + d = float_fn (); /* { dg-bogus "implicit" } */ +} + +/* There is no warning in non-evaluated contexts. */ + +void +non_evaluated (void) +{ + s = sizeof (f + 1.0); /* { dg-bogus "implicit" } */ + s = __alignof__ (f + 1.0); /* { dg-bogus "implicit" } */ + d = (__typeof__(f + 1.0))f; /* { dg-bogus "implicit" } */ + s = sizeof (i ? f : d); /* { dg-bogus "implicit" } */ +} Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 163924) +++ gcc/cp/typeck.c (working copy) @@ -265,6 +265,7 @@ cp_common_type (tree t1, tree t2) enum tree_code code2 = TREE_CODE (t2); tree attributes; + /* In what follows, we slightly generalize the rules given in [expr] so as to deal with `long long' and `complex'. First, merge the attributes. */ @@ -4362,7 +4363,14 @@ cp_build_binary_op (location_t location, if (!result_type && arithmetic_types_p && (shorten || common || short_compare)) - result_type = cp_common_type (type0, type1); + { + result_type = cp_common_type (type0, type1); + do_warn_double_promotion (result_type, type0, type1, + "implicit conversion from %qT to %qT " + "to match other operand of binary " + "expression", + location); + } if (!result_type) { Index: gcc/cp/call.c =================================================================== --- gcc/cp/call.c (revision 163924) +++ gcc/cp/call.c (working copy) @@ -4009,6 +4009,10 @@ build_conditional_expr (tree arg1, tree /* In this case, there is always a common type. */ result_type = type_after_usual_arithmetic_conversions (arg2_type, arg3_type); + do_warn_double_promotion (result_type, arg2_type, arg3_type, + "implicit conversion from %qT to %qT to " + "match other result of conditional", + input_location); if (TREE_CODE (arg2_type) == ENUMERAL_TYPE && TREE_CODE (arg3_type) == ENUMERAL_TYPE) @@ -5301,11 +5305,14 @@ convert_like_real (conversion *convs, tr tree convert_arg_to_ellipsis (tree arg) { + tree arg_type; + /* [expr.call] The lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed. */ arg = decay_conversion (arg); + arg_type = TREE_TYPE (arg); /* [expr.call] If the argument has integral or enumeration type that is subject @@ -5313,21 +5320,29 @@ convert_arg_to_ellipsis (tree arg) type that is subject to the floating point promotion (_conv.fpprom_), the value of the argument is converted to the promoted type before the call. */ - if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE - && (TYPE_PRECISION (TREE_TYPE (arg)) + if (TREE_CODE (arg_type) == REAL_TYPE + && (TYPE_PRECISION (arg_type) < TYPE_PRECISION (double_type_node)) - && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (arg)))) - arg = convert_to_real (double_type_node, arg); - else if (NULLPTR_TYPE_P (TREE_TYPE (arg))) + && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type))) + { + if (warn_double_promotion && !c_inhibit_evaluation_warnings) + warning (OPT_Wdouble_promotion, + "implicit conversion from %qT to %qT when passing " + "argument to function", + arg_type, double_type_node); + arg = convert_to_real (double_type_node, arg); + } + else if (NULLPTR_TYPE_P (arg_type)) arg = null_pointer_node; - else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg))) + else if (INTEGRAL_OR_ENUMERATION_TYPE_P (arg_type)) arg = perform_integral_promotions (arg); arg = require_complete_type (arg); + arg_type = TREE_TYPE (arg); if (arg != error_mark_node - && (type_has_nontrivial_copy_init (TREE_TYPE (arg)) - || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (arg)))) + && (type_has_nontrivial_copy_init (arg_type) + || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (arg_type))) { /* [expr.call] 5.2.2/7: Passing a potentially-evaluated argument of class type (Clause 9) @@ -5342,7 +5357,7 @@ convert_arg_to_ellipsis (tree arg) it is not potentially-evaluated. */ if (cp_unevaluated_operand == 0) error ("cannot pass objects of non-trivially-copyable " - "type %q#T through %<...%>", TREE_TYPE (arg)); + "type %q#T through %<...%>", arg_type); } return arg; Index: gcc/c-typeck.c =================================================================== --- gcc/c-typeck.c (revision 163924) +++ gcc/c-typeck.c (working copy) @@ -4036,40 +4036,6 @@ ep_convert_and_check (tree type, tree ex return convert (type, expr); } -/* RESULT_TYPE is the result of converting TYPE1 and TYPE2 to a common - type via c_common_type. If -Wdouble-promotion is in use, and the - conditions for warning have been met, issue a warning. GMSGID is - the warning message. It must have two %T specifiers for the type - that was converted (generally "float") and the type to which it was - converted (generally "double), respectively. LOC is the location - to which the awrning should refer. */ - -static void -do_warn_double_promotion (tree result_type, tree type1, tree type2, - const char *gmsgid, location_t loc) -{ - tree source_type; - - if (!warn_double_promotion) - return; - /* If the conversion will not occur at run-time, there is no need to - warn about it. */ - if (c_inhibit_evaluation_warnings) - return; - if (TYPE_MAIN_VARIANT (result_type) != double_type_node - && TYPE_MAIN_VARIANT (result_type) != complex_double_type_node) - return; - if (TYPE_MAIN_VARIANT (type1) == float_type_node - || TYPE_MAIN_VARIANT (type1) == complex_float_type_node) - source_type = type1; - else if (TYPE_MAIN_VARIANT (type2) == float_type_node - || TYPE_MAIN_VARIANT (type2) == complex_float_type_node) - source_type = type2; - else - return; - warning_at (loc, OPT_Wdouble_promotion, gmsgid, source_type, result_type); -} - /* Build and return a conditional expression IFEXP ? OP1 : OP2. If IFEXP_BCP then the condition is a call to __builtin_constant_p, and if folded to an integer constant then the unselected half may popd ^ permalink raw reply [flat|nested] 12+ messages in thread
* [wwwdocs] PATCH for -Wimplicit-double 2010-09-06 17:57 ` Mark Mitchell @ 2010-10-17 16:36 ` Gerald Pfeifer 0 siblings, 0 replies; 12+ messages in thread From: Gerald Pfeifer @ 2010-10-17 16:36 UTC (permalink / raw) To: gcc-patches, Mark Mitchell On Mon, 6 Sep 2010, Mark Mitchell wrote: >> OK, here's the version I checked in. I will now implement the C++ >> version of the warning. > Here's the C++ patch. I noticed this hasn't made it to the GCC 4.6 release notes yet, thus applied the patch below. Happy to make changes to improve upon this. Gerald Index: changes.html =================================================================== RCS file: /cvs/gcc/wwwdocs/htdocs/gcc-4.6/changes.html,v retrieving revision 1.50 diff -u -3 -p -r1.50 changes.html --- changes.html 6 Oct 2010 14:51:49 -0000 1.50 +++ changes.html 17 Oct 2010 16:05:46 -0000 @@ -106,6 +106,14 @@ <h3>C family</h3> + <ul> + <li>A new warning, enabled by <code>-Wno-double-promotion</code>, + has been added that warns about cases where a value of type + <code>float</code> is implicitly promoted to <code>double</code>. + This is especially helpful for CPUs that handle the former in + hardware, but emulate the latter in software.</li> + </ul> + <h3 id="C">C</h3> <ul> ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2010-10-17 16:07 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-09-03 16:04 RFA: PATCH: -Wimplicit-double Mark Mitchell 2010-09-03 17:38 ` Mark Mitchell 2010-09-03 17:45 ` Manuel López-Ibáñez 2010-09-03 17:51 ` Manuel López-Ibáñez 2010-09-03 18:06 ` Mark Mitchell 2010-09-03 19:03 ` Manuel López-Ibáñez 2010-09-03 19:13 ` Mark Mitchell 2010-09-04 8:35 ` Daniel Jacobowitz 2010-09-04 12:47 ` Gabriel Dos Reis 2010-09-05 22:15 ` Mark Mitchell 2010-09-06 17:57 ` Mark Mitchell 2010-10-17 16:36 ` [wwwdocs] PATCH for -Wimplicit-double Gerald Pfeifer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).