From 59dd8856eb0c8646db46941140467a5e342cec54 Mon Sep 17 00:00:00 2001 From: manu Date: Fri, 16 Mar 2007 23:32:12 +0000 Subject: [PATCH] 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. cp/ * 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. testsuite/ * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@123005 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 ++ gcc/c-common.c | 41 ++++++---- gcc/c-common.h | 1 + gcc/cp/ChangeLog | 12 +++ gcc/cp/call.c | 22 ++--- gcc/cp/cp-tree.h | 1 + gcc/cp/cvt.c | 23 ++++++ gcc/cp/typeck.c | 4 +- gcc/doc/invoke.texi | 6 ++ gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/g++.dg/warn/Wconversion-integer.C | 95 ++++++++++++++++++++++ .../g++.dg/warn/Wconversion-real-integer.C | 73 +++++++++++++++++ gcc/testsuite/g++.dg/warn/Wconversion-real.C | 85 +++++++++++++++++++ gcc/testsuite/g++.dg/warn/conv2.C | 3 +- 14 files changed, 345 insertions(+), 35 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wconversion-integer.C create mode 100644 gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C create mode 100644 gcc/testsuite/g++.dg/warn/Wconversion-real.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d00c15..008e18c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/c-common.c b/gcc/c-common.c index 36b87eb..8f71e69 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1168,7 +1168,7 @@ vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note) } /* 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 @@ conversion_warning (tree type, tree 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. */ +/* 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 @@ convert_and_check (tree type, tree expr) "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; } diff --git a/gcc/c-common.h b/gcc/c-common.h index 08ce460..b16a02d 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -671,6 +671,7 @@ struct varray_head_tag; 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); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 730c59e..f5d26c0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9d25298..8218ed4 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4245,11 +4245,12 @@ build_temp (tree expr, tree type, int flags, 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 @@ convert_conversion_warnings (tree totype, tree expr, tree fn, int argnum) 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 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, } 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 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, 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; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7d6ebc7..b9b3500 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4049,6 +4049,7 @@ extern tree convert_from_reference (tree); 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); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 4e628a5..947f1f2 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -593,6 +593,29 @@ cp_convert (tree type, tree expr) 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. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index ac6eb2b..6478b37 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -3837,9 +3837,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, 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; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index fa9ed7f..b3fe752 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -3396,6 +3396,12 @@ like @code{unsigned ui = -1}; and conversions to smaller types, like ((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} diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f761dcc..560fab9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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; diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-integer.C b/gcc/testsuite/g++.dg/warn/Wconversion-integer.C new file mode 100644 index 0000000..93f05cd --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wconversion-integer.C @@ -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" } */ + + diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C b/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C new file mode 100644 index 0000000..64d5199 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C @@ -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; +} + + diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-real.C b/gcc/testsuite/g++.dg/warn/Wconversion-real.C new file mode 100644 index 0000000..f769bac --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wconversion-real.C @@ -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; +} + + diff --git a/gcc/testsuite/g++.dg/warn/conv2.C b/gcc/testsuite/g++.dg/warn/conv2.C index 4dfeb86..45f5183 100644 --- a/gcc/testsuite/g++.dg/warn/conv2.C +++ b/gcc/testsuite/g++.dg/warn/conv2.C @@ -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" } -- 2.7.4