This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH]: warning on implicit float->int
- To: gcc-patches at gcc dot gnu dot org, j dot kuipers at chello dot nl
- Subject: [C++ PATCH]: warning on implicit float->int
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Mon, 28 Feb 2000 10:12:03 +0000
- Organization: CodeSourcery, LLC
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
}