public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* 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).