invoke.texi (-Wconversion): Document warnings specific to C++.

2007-03-16  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

	* 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.

From-SVN: r123005
This commit is contained in:
Manuel López-Ibáñez 2007-03-16 23:32:12 +00:00
parent aefd26064c
commit 07231d4f83
14 changed files with 345 additions and 35 deletions

View File

@ -1,3 +1,10 @@
2007-03-16 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
* 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 <dave.anglin@nrc-cnrc.gc.ca>
* pa.c (attr_length_call): Partially revert change of 2007-03-09.

View File

@ -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;
}

View File

@ -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);

View File

@ -1,3 +1,15 @@
2007-03-16 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
* 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 <manu@gcc.gnu.org>
PR c++/30891

View File

@ -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 %<false%> 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;

View File

@ -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);

View File

@ -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. */

View File

@ -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;

View File

@ -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}

View File

@ -1,3 +1,10 @@
2007-03-16 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
* 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 <richard@codesourcery.com>
* gcc.dg/intmax_t-1.c: Restrict XFAIL to VxWorks kernels;

View File

@ -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 <limits.h>
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" } */

View File

@ -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 <limits.h>
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;
}

View File

@ -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;
}

View File

@ -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" }