Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 123004) +++ gcc/doc/invoke.texi (revision 123005) @@ -3396,6 +3396,12 @@ ((int) x)} and @code{ui = (unsigned) -1}, or if the value is not changed by the conversion like in @code{abs (2.0)}. +For C++, also warn for conversions between @code{NULL} and non-pointer +types; confusing overload resolution for user-defined conversions; and +conversions that will never use a type conversion operator: +conversions to @code{void}, the same type, a base class or a reference +to them. + @item -Wempty-body @opindex Wempty-body An empty body occurs in an @samp{if}, @samp{else} or @samp{do while} Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 123004) +++ gcc/ChangeLog (revision 123005) @@ -1,3 +1,10 @@ +2007-03-16 Manuel Lopez-Ibanez + + * doc/invoke.texi (-Wconversion): Document warnings specific to C++. + * c-common.c (convert_and_check): Move warning logic to... + (warnings_for_convert_and_check): ...here. Define. + * c-common.h (warnings_for_convert_and_check): Declare. + 2007-03-16 John David Anglin * pa.c (attr_length_call): Partially revert change of 2007-03-09. Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 123004) +++ gcc/testsuite/ChangeLog (revision 123005) @@ -1,3 +1,10 @@ +2007-03-16 Manuel Lopez-Ibanez + + * g++.dg/warn/Wconversion-integer.C: New + * g++.dg/warn/Wconversion-real.C: New. + * g++.dg/warn/Wconversion-real-integer.C: New. + * g++.dg/warn/conv2.C: Updated. + 2007-03-16 Richard Sandiford * gcc.dg/intmax_t-1.c: Restrict XFAIL to VxWorks kernels; Index: gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C (revision 0) +++ gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C (revision 123005) @@ -0,0 +1,73 @@ +/* Test for diagnostics for Wconversion between floating-point and + integers. C++ equivalent of + gcc/testsuite/gcc.dg/Wconversion-real-integer.c */ + +/* { dg-do compile } +/* { dg-options "-Wconversion" } */ + +#include + +void fsi (signed int x); +void fui (unsigned int x); +void ffloat (float x); +void fdouble (double x); + +float vfloat; +double vdouble; + +void h (void) +{ + unsigned int ui = 3; + int si = 3; + unsigned char uc = 3; + signed char sc = 3; + float f = 3; + double d = 3; + + fsi (3.1f); /* { dg-warning "conversion" } */ + si = 3.1f; /* { dg-warning "conversion" } */ + fsi (3.1); /* { dg-warning "conversion" } */ + si = 3.1; /* { dg-warning "conversion" } */ + fsi (d); /* { dg-warning "conversion" } */ + si = d; /* { dg-warning "conversion" } */ + fui (-1.0); /* { dg-warning "overflow" } */ + ui = -1.0; /* { dg-warning "overflow" } */ + ffloat (INT_MAX); /* { dg-warning "conversion" } */ + vfloat = INT_MAX; /* { dg-warning "conversion" } */ + ffloat (16777217); /* { dg-warning "conversion" } */ + vfloat = 16777217; /* { dg-warning "conversion" } */ + ffloat (si); /* { dg-warning "conversion" } */ + vfloat = si; /* { dg-warning "conversion" } */ + ffloat (ui); /* { dg-warning "conversion" } */ + vfloat = ui; /* { dg-warning "conversion" } */ + + fsi (3); + si = 3; + fsi (3.0f); + si = 3.0f; + fsi (3.0); + si = 3.0; + fsi (16777217.0f); + si = 16777217.0f; + fsi ((int) 3.1); + si = (int) 3.1; + ffloat (3U); + vfloat = 3U; + ffloat (3); + vfloat = 3; + ffloat (INT_MIN); + vfloat = INT_MIN; + ffloat (uc); + vfloat = uc; + ffloat (sc); + vfloat = sc; + + fdouble (UINT_MAX); + vdouble = UINT_MAX; + fdouble (ui); + vdouble = ui; + fdouble (si); + vdouble = si; +} + + Index: gcc/testsuite/g++.dg/warn/Wconversion-real.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wconversion-real.C (revision 0) +++ gcc/testsuite/g++.dg/warn/Wconversion-real.C (revision 123005) @@ -0,0 +1,85 @@ +/* Test for diagnostics for Wconversion for floating-point. + C++ equivalent of gcc/testsuite/gcc.dg/Wconversion-real.c */ + +/* { dg-do compile } +/* { dg-options "-Wconversion" } */ + +float vfloat; +double vdouble; +long double vlongdouble; + +void ffloat (float f); +void fdouble (double d); +void flongdouble (long double ld); + +void h (void) +{ + float f = 0; + double d = 0; + long double ld = 0; + + ffloat (3.1); /* { dg-warning "conversion" } */ + vfloat = 3.1; /* { dg-warning "conversion" } */ + ffloat (3.1L); /* { dg-warning "conversion" } */ + vfloat = 3.1L; /* { dg-warning "conversion" } */ + fdouble (3.1L); /* { dg-warning "conversion" "" { target large_long_double } } */ + vdouble = 3.1L; /* { dg-warning "conversion" "" { target large_long_double } } */ + ffloat (vdouble); /* { dg-warning "conversion" } */ + vfloat = vdouble; /* { dg-warning "conversion" } */ + ffloat (vlongdouble); /* { dg-warning "conversion" } */ + vfloat = vlongdouble; /* { dg-warning "conversion" } */ + fdouble (vlongdouble); /* { dg-warning "conversion" "" { target large_long_double } } */ + vdouble = vlongdouble; /* { dg-warning "conversion" "" { target large_long_double } } */ + + + ffloat ((float) 3.1); + vfloat = (float) 3.1; + ffloat ((float) 3.1L); + vfloat = (float) 3.1L; + fdouble ((double) 3.1L); + vdouble = (double) 3.1L; + ffloat ((float) vdouble); + vfloat = (float) vdouble; + ffloat ((float) vlongdouble); + vfloat = (float) vlongdouble; + fdouble ((double) vlongdouble); + vdouble = (double) vlongdouble; + + + ffloat (3.0); + vfloat = 3.0; + ffloat (3.1f); + vfloat = 3.1f; + ffloat (0.25L); + vfloat = 0.25L; + + + fdouble (3.0); + vdouble = 3.0; + fdouble (3.1f); + vdouble = 3.1f; + fdouble (0.25L); + vdouble = 0.25L; + + flongdouble (3.0); + vlongdouble = 3.0; + flongdouble (3.1f); + vlongdouble = 3.1f; + flongdouble (0.25L); + vlongdouble = 0.25L; + + ffloat (f); + vfloat = f; + fdouble (f); + vdouble = f; + fdouble (d); + vdouble = d; + flongdouble (f); + vlongdouble = f; + flongdouble (d); + vlongdouble = d; + flongdouble (ld); + vlongdouble = ld; +} + + Index: gcc/testsuite/g++.dg/warn/Wconversion-integer.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wconversion-integer.C (revision 0) +++ gcc/testsuite/g++.dg/warn/Wconversion-integer.C (revision 123005) @@ -0,0 +1,95 @@ +/* Test for diagnostics for implicit conversions between integer types + C++ equivalent of gcc/testsuite/gcc.dg/Wconversion-integer.c */ + +// { dg-do compile } +// { dg-options "-fsigned-char -Wconversion" } + +#include + +void fsc (signed char sc); +void fuc (unsigned char uc); +unsigned fui (unsigned int ui); +void fsi (signed int ui); + +void h (int x) +{ + unsigned int ui = 3; + int si = 3; + unsigned char uc = 3; + signed char sc = 3; + + fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + uc = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + fuc ('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + uc = x ? 1U : -1; /* { dg-warning "conversion" } */ + /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 25 } */ + uc = x ? SCHAR_MIN : 1U; /* { dg-warning "conversion" } */ + /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 27 } */ + + uc = x ? 1 : -1; /* { dg-warning "conversion" } */ + + uc = x ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */ + + fuc ('A'); + uc = 'A'; + uc = (unsigned char) -1; + + fui (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + ui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + ui = x ? 1U : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + ui = x ? INT_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + ui = ui ? SCHAR_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + ui = 1U * -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + ui = ui + INT_MIN; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + ui = x ? 1 : -1; /* { dg-warning "conversion" } */ + ui = ui ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */ + + ui = -1 * (1 * -1); + ui = (unsigned) -1; + + fsc (uc); /* { dg-warning "conversion" } */ + sc = uc; /* { dg-warning "conversion" } */ + fuc (sc); /* { dg-warning "conversion" } */ + uc = sc; /* { dg-warning "conversion" } */ + fsi (ui); /* { dg-warning "conversion" } */ + si = ui; /* { dg-warning "conversion" } */ + fui (si); /* { dg-warning "conversion" } */ + ui = si; /* { dg-warning "conversion" } */ + fui (sc); /* { dg-warning "conversion" } */ + ui = sc; /* { dg-warning "conversion" } */ + + fui ('\xa0');/* { dg-warning "negative integer implicitly converted to unsigned type" } */ + ui = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + + fsi (si); + fui (ui); + fsi (uc); + si = uc; + fui (uc); + ui = uc; + fui ('A'); + ui = 'A'; + fsi ('A'); + si = 'A'; + + + fsi (UINT_MAX - 1); /* { dg-warning "conversion" } */ + si = UINT_MAX - 1; /* { dg-warning "conversion" } */ + fsi (UINT_MAX - 1U); /* { dg-warning "conversion" } */ + si = UINT_MAX - 1U; /* { dg-warning "conversion" } */ + fsi (UINT_MAX/3U); + si = UINT_MAX/3U; + fsi (UINT_MAX/3); + si = UINT_MAX/3; + fui (UINT_MAX - 1); + ui = UINT_MAX - 1; + + fsi (0x80000000); /* { dg-warning "conversion" } */ + si = 0x80000000; /* { dg-warning "conversion" } */ +} + + +unsigned fui (unsigned a) { return a + -1; } /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + + Index: gcc/testsuite/g++.dg/warn/conv2.C =================================================================== --- gcc/testsuite/g++.dg/warn/conv2.C (revision 123004) +++ gcc/testsuite/g++.dg/warn/conv2.C (revision 123005) @@ -1,4 +1,5 @@ // PR c++/13932 // { dg-options "-Wconversion" } -int i = 1.; // { dg-warning "converting" } +int i = 1.; +int j = 1.1; // { dg-warning "conversion" } Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 123004) +++ gcc/cp/typeck.c (revision 123005) @@ -3837,9 +3837,9 @@ if (! converted) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert (result_type, op0); + op0 = cp_convert_and_check (result_type, op0); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert (result_type, op1); + op1 = cp_convert_and_check (result_type, op1); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; Index: gcc/cp/call.c =================================================================== --- gcc/cp/call.c (revision 123004) +++ gcc/cp/call.c (revision 123005) @@ -4245,11 +4245,12 @@ return expr; } -/* Perform warnings about conversion of EXPR to type TOTYPE. +/* Perform warnings about peculiar, but valid, conversions from/to NULL. + EXPR is implicitly converted to type TOTYPE. FN and ARGNUM are used for diagnostics. */ static void -convert_conversion_warnings (tree totype, tree expr, tree fn, int argnum) +conversion_null_warnings (tree totype, tree expr, tree fn, int argnum) { tree t = non_reference (totype); @@ -4263,19 +4264,8 @@ warning (OPT_Wconversion, "converting to non-pointer type %qT from NULL", t); } - /* Warn about assigning a floating-point type to an integer type. */ - if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE - && TREE_CODE (t) == INTEGER_TYPE) - { - if (fn) - warning (OPT_Wconversion, "passing %qT for argument %P to %qD", - TREE_TYPE (expr), argnum, fn); - else - warning (OPT_Wconversion, "converting to %qT from %qT", t, TREE_TYPE (expr)); - } - /* Issue warnings if "false" is converted to a NULL pointer */ - if (expr == boolean_false_node && fn && POINTER_TYPE_P (t)) + else if (expr == boolean_false_node && fn && POINTER_TYPE_P (t)) warning (OPT_Wconversion, "converting % to pointer type for argument %P of %qD", argnum, fn); @@ -4328,7 +4318,7 @@ } if (issue_conversion_warnings) - convert_conversion_warnings (totype, expr, fn, argnum); + conversion_null_warnings (totype, expr, fn, argnum); switch (convs->kind) { @@ -4415,7 +4405,7 @@ expr = convert_like_real (convs->u.next, expr, fn, argnum, convs->kind == ck_ref_bind ? -1 : 1, - /*issue_conversion_warnings=*/false, + convs->kind == ck_ref_bind ? issue_conversion_warnings : false, c_cast_p); if (expr == error_mark_node) return error_mark_node; Index: gcc/cp/cvt.c =================================================================== --- gcc/cp/cvt.c (revision 123004) +++ gcc/cp/cvt.c (revision 123005) @@ -593,6 +593,29 @@ return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); } +/* C++ equivalent of convert_and_check but using cp_convert as the + conversion function. + + Convert EXPR to TYPE, warning about conversion problems with constants. + Invoke this function on every expression that is converted implicitly, + i.e. because of language rules and not because of an explicit cast. */ + +tree +cp_convert_and_check (tree type, tree expr) +{ + tree result; + + if (TREE_TYPE (expr) == type) + return expr; + + result = cp_convert (type, expr); + + if (!skip_evaluation && !TREE_OVERFLOW_P (expr)) + warnings_for_convert_and_check (type, expr, result); + + return result; +} + /* Conversion... FLAGS indicates how we should behave. */ Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 123004) +++ gcc/cp/cp-tree.h (revision 123005) @@ -4049,6 +4049,7 @@ extern tree force_rvalue (tree); extern tree ocp_convert (tree, tree, int, int); extern tree cp_convert (tree, tree); +extern tree cp_convert_and_check (tree, tree); extern tree convert_to_void (tree, const char */*implicit context*/); extern tree convert_force (tree, tree, int); extern tree build_expr_type_conversion (int, tree, bool); Index: gcc/cp/ChangeLog =================================================================== --- gcc/cp/ChangeLog (revision 123004) +++ gcc/cp/ChangeLog (revision 123005) @@ -1,3 +1,15 @@ +2007-03-16 Manuel Lopez-Ibanez + + * cvt.c (cp_convert_and_check) : Define. + * cp-tree.h (cp_convert_and_check): Declare. + * call.c (convert_conversion_warnings): Rename to + conversion_null_warnings. The warning for floating-point to + integer is handled by convert_and_check in convert_like_real. + (convert_like_real): convert_conversion_warnings was renamed as + conversion_null_warnings. + * typeck.c (build_binary_op): Use cp_convert_and_check to warn for + overflow and changes of value during conversion. + 2007-03-15 Manuel Lopez-Ibanez PR c++/30891 Index: gcc/c-common.c =================================================================== --- gcc/c-common.c (revision 123004) +++ gcc/c-common.c (revision 123005) @@ -1168,7 +1168,7 @@ } /* Warns if the conversion of EXPR to TYPE may alter a value. - This function is called from convert_and_check. */ + This is a helper function for warnings_for_convert_and_check. */ static void conversion_warning (tree type, tree expr) @@ -1276,23 +1276,13 @@ } } -/* Convert EXPR to TYPE, warning about conversion problems with constants. - Invoke this function on every expression that is converted implicitly, - i.e. because of language rules and not because of an explicit cast. */ +/* Produce warnings after a conversion. RESULT is the result of + converting EXPR to TYPE. This is a helper function for + convert_and_check and cp_convert_and_check. */ -tree -convert_and_check (tree type, tree expr) +void +warnings_for_convert_and_check (tree type, tree expr, tree result) { - tree result; - - if (TREE_TYPE (expr) == type) - return expr; - - result = convert (type, expr); - - if (skip_evaluation || TREE_OVERFLOW_P (expr)) - return result; - if (TREE_CODE (expr) == INTEGER_CST && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE) @@ -1332,7 +1322,26 @@ "overflow in implicit constant conversion"); else if (warn_conversion) conversion_warning (type, expr); +} + + +/* Convert EXPR to TYPE, warning about conversion problems with constants. + Invoke this function on every expression that is converted implicitly, + i.e. because of language rules and not because of an explicit cast. */ + +tree +convert_and_check (tree type, tree expr) +{ + tree result; + + if (TREE_TYPE (expr) == type) + return expr; + result = convert (type, expr); + + if (!skip_evaluation && !TREE_OVERFLOW_P (expr)) + warnings_for_convert_and_check (type, expr, result); + return result; } Index: gcc/c-common.h =================================================================== --- gcc/c-common.h (revision 123004) +++ gcc/c-common.h (revision 123005) @@ -671,6 +671,7 @@ extern void constant_expression_warning (tree); extern void strict_aliasing_warning (tree, tree, tree); extern void empty_if_body_warning (tree, tree); +extern void warnings_for_convert_and_check (tree, tree, tree); extern tree convert_and_check (tree, tree); extern void overflow_warning (tree); extern void warn_logical_operator (enum tree_code, tree, tree);