This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[C++ PATCH]: warning on implicit float->int


Hi,
here's a patch to fix the lack of warnings reported by Johan Kuipers
(http://gcc.gnu.org/ml/gcc-bugs/2000-02/msg00503.html). The problem
was rather more than Johan indicated. With an overloaded
function call (or a ctor), build_over_call would simply construct
the legal conversions for the selected function call. It would not
call convert_for_initialization, which would give the warning.
For a non-overloaded call build_over_call is not involved, and you
will get the warning.

So, I've broken dubious_conversion_warnings out of
convert_for_assignment, and called that from convert_for_assignment
and build_over_call. The check for using NULL in non-pointer contexts
was duplicated in both these places, so that's combined too.

I also made these warnings conditional on -W, as IMO they shouldn't
be unconditional. invoke.texi is updated to document this, and some
testcase tweaked to supply -W.

ok?

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
gcc
2000-02-26  Nathan Sidwell  <nathan@codesourcery.com>

	* invoke.texi (-W): Document implicit conversion warnings.

gcc/cp
2000-02-26  Nathan Sidwell  <nathan@codesourcery.com>

	* cp-tree.h (convert_default_arg): Add PARMNUM parameter.
	(dubious_conversion_warnings): Declare.
	* typeck.c (convert_arguments): Adjust convert_default_arg call.
	(dubious_conversion_warnings): New function, broken
	out of convert_for_assignment. Conditionalize on -W.
	(convert_for_assignment): Adjust.
	* call.c (convert_default_arg): Add PARMNUM parameter. Adjust
	convert_for_initialization calls.
	(build_over_call): Use dubious_conversion_warnings. Adjust
	convert_default_arg calls.

gcc/testsuite
2000-02-26  Nathan Sidwell  <nathan@codesourcery.com>

	* g++.old-deja/g++.other/null1.C: Add -W.
	* g++.old-deja/g++.other/warn4.C: Likewise.
	* g++.old-deja/g++.other/warn5.C: New test.

Index: invoke.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/invoke.texi,v
retrieving revision 1.174
diff -c -3 -p -r1.174 invoke.texi
*** invoke.texi	2000/02/21 20:48:23	1.174
--- invoke.texi	2000/02/26 23:04:24
*************** For example, the following code would ca
*** 1719,1724 ****
--- 1719,1731 ----
  struct s @{ int f, g, h; @};
  struct s x = @{ 3, 4 @};
  @end smallexample
+ 
+ @item
+ Converting a floating point type to an integral type. Using @ode{NULL} as a
+ non-pointer type. Converting a negative signed integral value to an
+ unsigned type. These conversions, though legal, are often mistakes.
+ This is a C++ specific warning.
+ 
  @end itemize
  
  @item -Wfloat-equal
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/call.c,v
retrieving revision 1.196
diff -c -3 -p -r1.196 call.c
*** call.c	2000/02/22 07:25:27	1.196
--- call.c	2000/02/26 23:04:32
*************** convert_type_from_ellipsis (type)
*** 3856,3865 ****
     conversions.  Return the converted value.  */
  
  tree
! convert_default_arg (type, arg, fn)
       tree type;
       tree arg;
       tree fn;
  {
    if (fn && DECL_TEMPLATE_INFO (fn))
      arg = tsubst_default_argument (fn, type, arg);
--- 3856,3866 ----
     conversions.  Return the converted value.  */
  
  tree
! convert_default_arg (type, arg, fn, parmnum)
       tree type;
       tree arg;
       tree fn;
+      int parmnum;
  {
    if (fn && DECL_TEMPLATE_INFO (fn))
      arg = tsubst_default_argument (fn, type, arg);
*************** convert_default_arg (type, arg, fn)
*** 3870,3876 ****
      {
        arg = digest_init (type, arg, 0);
        arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
! 					"default argument", 0, 0);
      }
    else
      {
--- 3871,3877 ----
      {
        arg = digest_init (type, arg, 0);
        arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
! 					"default argument", fn, parmnum);
      }
    else
      {
*************** convert_default_arg (type, arg, fn)
*** 3879,3885 ****
  	arg = copy_node (arg);
  
        arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
! 					"default argument", 0, 0);
        if (PROMOTE_PROTOTYPES
  	  && (TREE_CODE (type) == INTEGER_TYPE
  	      || TREE_CODE (type) == ENUMERAL_TYPE)
--- 3880,3886 ----
  	arg = copy_node (arg);
  
        arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
! 					"default argument", fn, parmnum);
        if (PROMOTE_PROTOTYPES
  	  && (TREE_CODE (type) == INTEGER_TYPE
  	      || TREE_CODE (type) == ENUMERAL_TYPE)
*************** build_over_call (cand, args, flags)
*** 3980,3994 ****
  	    }
  	  val = convert_for_initialization
  	    (NULL_TREE, type, val, LOOKUP_NORMAL,
! 	     "argument passing", fn, i - is_method);
  	}
        else
  	{
! 	  /* Issue warnings about peculiar, but legal, uses of NULL.  */
! 	  if (ARITHMETIC_TYPE_P (TREE_VALUE (parm))
! 	      && TREE_VALUE (arg) == null_node)
! 	    cp_warning ("converting NULL to non-pointer type");
! 	    
  	  val = convert_like (conv, TREE_VALUE (arg));
  	}
  
--- 3981,3994 ----
  	    }
  	  val = convert_for_initialization
  	    (NULL_TREE, type, val, LOOKUP_NORMAL,
! 	     "argument", fn, i - is_method);
  	}
        else
  	{
! 	  val = TREE_VALUE (arg);
! 	  val = dubious_conversion_warnings
! 	    (TREE_VALUE (parm), val,
!              "argument", fn, i - is_method);
  	  val = convert_like (conv, TREE_VALUE (arg));
  	}
  
*************** build_over_call (cand, args, flags)
*** 4001,4012 ****
      }
  
    /* Default arguments */
!   for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
      converted_args 
        = tree_cons (NULL_TREE, 
  		   convert_default_arg (TREE_VALUE (parm), 
  					TREE_PURPOSE (parm),
! 					fn),
  		   converted_args);
  
    /* Ellipsis */
--- 4001,4012 ----
      }
  
    /* Default arguments */
!   for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)
      converted_args 
        = tree_cons (NULL_TREE, 
  		   convert_default_arg (TREE_VALUE (parm), 
  					TREE_PURPOSE (parm),
! 					fn, i - is_method),
  		   converted_args);
  
    /* Ellipsis */
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.407
diff -c -3 -p -r1.407 cp-tree.h
*** cp-tree.h	2000/02/22 07:25:27	1.407
--- cp-tree.h	2000/02/26 23:04:33
*************** extern tree build_op_delete_call		PARAMS
*** 3584,3590 ****
  extern int can_convert				PARAMS ((tree, tree));
  extern int can_convert_arg			PARAMS ((tree, tree, tree));
  extern int enforce_access                       PARAMS ((tree, tree));
! extern tree convert_default_arg                 PARAMS ((tree, tree, tree));
  extern tree convert_arg_to_ellipsis             PARAMS ((tree));
  extern tree build_x_va_arg                      PARAMS ((tree, tree));
  extern tree convert_type_from_ellipsis          PARAMS ((tree));
--- 3584,3590 ----
  extern int can_convert				PARAMS ((tree, tree));
  extern int can_convert_arg			PARAMS ((tree, tree, tree));
  extern int enforce_access                       PARAMS ((tree, tree));
! extern tree convert_default_arg                 PARAMS ((tree, tree, tree, int));
  extern tree convert_arg_to_ellipsis             PARAMS ((tree));
  extern tree build_x_va_arg                      PARAMS ((tree, tree));
  extern tree convert_type_from_ellipsis          PARAMS ((tree));
*************** extern tree build_const_cast			PARAMS ((
*** 4375,4380 ****
--- 4375,4381 ----
  extern tree build_c_cast			PARAMS ((tree, tree));
  extern tree build_x_modify_expr			PARAMS ((tree, enum tree_code, tree));
  extern tree build_modify_expr			PARAMS ((tree, enum tree_code, tree));
+ extern tree dubious_conversion_warnings         PARAMS ((tree, tree, const char *, tree, int));
  extern tree convert_for_initialization		PARAMS ((tree, tree, tree, int, const char *, tree, int));
  extern void c_expand_asm_operands		PARAMS ((tree, tree, tree, tree, int, char *, int));
  extern void c_expand_return			PARAMS ((tree));
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/typeck.c,v
retrieving revision 1.247
diff -c -3 -p -r1.247 typeck.c
*** typeck.c	2000/02/22 07:25:31	1.247
--- typeck.c	2000/02/26 23:04:40
*************** convert_arguments (typelist, values, fnd
*** 3210,3216 ****
  	      tree parmval 
  		= convert_default_arg (TREE_VALUE (typetail), 
  				       TREE_PURPOSE (typetail), 
! 				       fndecl);
  
  	      if (parmval == error_mark_node)
  		return error_mark_node;
--- 3210,3216 ----
  	      tree parmval 
  		= convert_default_arg (TREE_VALUE (typetail), 
  				       TREE_PURPOSE (typetail), 
! 				       fndecl, i);
  
  	      if (parmval == error_mark_node)
  		return error_mark_node;
*************** pfn_from_ptrmemfunc (t)
*** 6407,6412 ****
--- 6407,6468 ----
  	     pfn_identifier, NULL_TREE, 0)); 
  }
  
+ /* Expression EXPR is about to be implicitly converted to TYPE.  Warn
+    if this is a potentially dangerous thing to do.  Returns a possibly
+    marked EXPR.  */
+ 
+ tree
+ dubious_conversion_warnings (type, expr, errtype, fndecl, parmnum)
+      tree type;
+      tree expr;
+      const char *errtype;
+      tree fndecl;
+      int parmnum;
+ {
+   if (!extra_warnings)
+     return expr;
+   
+   /* Issue warnings about peculiar, but legal, uses of NULL.  */
+   if (ARITHMETIC_TYPE_P (type) && expr == null_node)
+     {
+       if (fndecl)
+         cp_warning ("passing NULL used for non-pointer %s %P of `%D'",
+                     errtype, parmnum, fndecl);
+       else
+         cp_warning ("%s to non-pointer type `%T' from NULL", errtype, type);
+     }
+   
+   /* Warn about assigning a floating-point type to an integer type.  */
+   if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+       && TREE_CODE (type) == INTEGER_TYPE)
+     {
+       if (fndecl)
+ 	cp_warning ("passing `%T' for %s %P of `%D'",
+ 		    TREE_TYPE (expr), errtype, parmnum, fndecl);
+       else
+ 	cp_warning ("%s to `%T' from `%T'", errtype, type, TREE_TYPE (expr));
+     }
+   /* And warn about assigning a negative value to an unsigned
+      variable.  */
+   else if (TREE_UNSIGNED (type) && TREE_CODE (type) != BOOLEAN_TYPE)
+     {
+       if (TREE_CODE (expr) == INTEGER_CST
+ 	  && TREE_NEGATED_INT (expr))
+ 	{
+ 	  if (fndecl)
+ 	    cp_warning ("passing negative value `%E' for %s %P of `%D'",
+ 			expr, errtype, parmnum, fndecl);
+ 	  else
+ 	    cp_warning ("%s of negative value `%E' to `%T'",
+ 			errtype, expr, type);
+ 	}
+       overflow_warning (expr);
+       if (TREE_CONSTANT (expr))
+ 	expr = fold (expr);
+     }
+   return expr;
+ }
+ 
  /* Convert value RHS to type TYPE as preparation for an assignment to
     an lvalue of type TYPE.  ERRTYPE is a string to use in error
     messages: "assignment", "return", etc.  If FNDECL is non-NULL, we
*************** convert_for_assignment (type, rhs, errty
*** 6442,6453 ****
    if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
      return error_mark_node;
  
!   /* Issue warnings about peculiar, but legal, uses of NULL.  We
!      do this *before* the call to decl_constant_value so as to
!      avoid duplicate warnings on code like `const int I = NULL;
!      f(I);'.  */
!   if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
!     cp_warning ("converting NULL to non-pointer type");
  
    /* The RHS of an assignment cannot have void type.  */
    if (coder == VOID_TYPE)
--- 6498,6504 ----
    if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
      return error_mark_node;
  
!   rhs = dubious_conversion_warnings (type, rhs, errtype, fndecl, parmnum);
  
    /* The RHS of an assignment cannot have void type.  */
    if (coder == VOID_TYPE)
*************** convert_for_assignment (type, rhs, errty
*** 6461,6494 ****
      rhs = DECL_INITIAL (rhs);
    else if (TREE_READONLY_DECL_P (rhs))
      rhs = decl_constant_value (rhs);
- 
-   /* Warn about assigning a floating-point type to an integer type.  */
-   if (coder == REAL_TYPE && codel == INTEGER_TYPE)
-     {
-       if (fndecl)
- 	cp_warning ("`%T' used for argument %P of `%D'",
- 		    rhstype, parmnum, fndecl);
-       else
- 	cp_warning ("%s to `%T' from `%T'", errtype, type, rhstype);
-     }
-   /* And warn about assigning a negative value to an unsigned
-      variable.  */
-   else if (TREE_UNSIGNED (type) && codel != BOOLEAN_TYPE)
-     {
-       if (TREE_CODE (rhs) == INTEGER_CST
- 	  && TREE_NEGATED_INT (rhs))
- 	{
- 	  if (fndecl)
- 	    cp_warning ("negative value `%E' passed as argument %P of `%D'",
- 			rhs, parmnum, fndecl);
- 	  else
- 	    cp_warning ("%s of negative value `%E' to `%T'",
- 			errtype, rhs, type);
- 	}
-       overflow_warning (rhs);
-       if (TREE_CONSTANT (rhs))
- 	rhs = fold (rhs);
-     }
  
    /* [expr.ass]
  
--- 6512,6517 ----
Index: testsuite/g++.old-deja/g++.other/null1.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.other/null1.C,v
retrieving revision 1.6
diff -c -3 -p -r1.6 null1.C
*** null1.C	1999/07/04 22:16:22	1.6
--- null1.C	2000/02/26 23:04:44
***************
*** 1,4 ****
--- 1,5 ----
  // Build don't run:
+ // Special g++ Options: -ansi -pedantic-errors -W
  
  #include <cstddef>
  
*************** int main()
*** 28,35 ****
  
    i != NULL; // WARNING - NULL used in arithmetic
    NULL != z; // WARNING - NULL used in arithmetic
!   k != NULL; // No warning: decay conversion
!   NULL != a; // Likewise.
    -NULL;     // WARNING - converting NULL to non-pointer type
    +NULL;     // WARNING - converting NULL to non-pointer type
    ~NULL;     // WARNING - converting NULL to non-pointer type
--- 29,36 ----
  
    i != NULL; // WARNING - NULL used in arithmetic
    NULL != z; // WARNING - NULL used in arithmetic
!   (void) (k != NULL); // No warning: decay conversion
!   (void) (NULL != a); // Likewise.
    -NULL;     // WARNING - converting NULL to non-pointer type
    +NULL;     // WARNING - converting NULL to non-pointer type
    ~NULL;     // WARNING - converting NULL to non-pointer type
*************** int main()
*** 40,44 ****
    g(NULL);   // WARNING - converting NULL to int
    h<NULL>(); // WARNING - NULL bound to integer template parameter
    l(NULL);   // WARNING - converting NULL to int
!   NULL && NULL; // No warning: converting NULL to bool is OK
  }
--- 41,45 ----
    g(NULL);   // WARNING - converting NULL to int
    h<NULL>(); // WARNING - NULL bound to integer template parameter
    l(NULL);   // WARNING - converting NULL to int
!   (void) (NULL && NULL); // No warning: converting NULL to bool is OK
  }
Index: testsuite/g++.old-deja/g++.other/warn4.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.other/warn4.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 warn4.C
*** warn4.C	1999/11/22 16:10:58	1.1
--- warn4.C	2000/02/26 23:04:44
***************
*** 1,4 ****
--- 1,5 ----
  // Build don't link:
+ // Special g++ Options: -ansi -pedantic-errors -W
  
  // Copyright (C) 1999 Free Software Foundation, Inc.
  // Contributed by Nathan Sidwell 21 Nov 1999 <nathan@acm.org>

// Build don't link:
// Special g++ Options: -ansi -pedantic-errors -W

// Copyright (C) 2000 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 24 Feb 2000 <nathan@codesourcery.com>

// derived from a bug report by Johan Kuipers <j.kuipers@chello.nl>
// initialization to 'int' from to 'double' We expect consistent warnings
// whenever a float is implicitly truncated to int

struct X
{
  X (int);
  X (int, int);
};

void foo (int);
void wibble (int);
void wibble (int, int);
void punk (int = 3.5);
void rock ();
void rock (int, int = 3.5);

void fn ()
{
  X x1(3.5);        // WARNING - double to int
  X x2(3.5f);       // WARNING - float to int
  X x3(1, 3.5);     // WARNING - double to int
  X x4(1, 3.5f);    // WARNING - float to int
  X x5(3.5, 1);     // WARNING - double to int
  X x6(3.5f, 1);    // WARNING - float to int

  X y1 = 3.5;       // WARNING - double to int
  X y2 = 3.5f;      // WARNING - float to int

  int j1 (3.5);     // WARNING - double to int
  int j2 (3.5f);    // WARNING - float to int

  int k1 = 3.5;     // WARNING - double to int
  int k2 = 3.5f;    // WARNING - float to int
  
  j1 = 3.5;         // WARNING - double to int
  j2 = 3.5f;        // WARNING - float to int
  
  foo (3.5);        // WARNING - double to int
  foo (3.5f);       // WARNING - float to int
  
  wibble (3.5);     // WARNING - double to int
  wibble (3.5f);    // WARNING - float to int
  wibble (1, 3.5);  // WARNING - double to int
  wibble (1, 3.5f); // WARNING - float to int
  wibble (3.5, 1);  // WARNING - double to int
  wibble (3.5f, 1); // WARNING - float to int
  
  punk ();          // WARNING - double to int
  rock (1);         // WARNING - double to int
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]