re PR middle-end/11492 (Bogus warning with -Wsign-compare)

2008-10-29  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

	PR 11492
	* c-common.c (min_precision): Move to...
	* tree.c (tree_int_cst_min_precision): ... to here. Renamed.
	* tree.h (tree_int_cst_min_precision): Declare.
	* c-common.h (min_precision): Delete declaration.
	* fold-const.c (tree_binary_nonnegative_warnv_p): Handle
	multiplication of non-negative integer constants.
	* c-decl.c (check_bitfield_type_and_width): Rename min_precision to
	tree_int_cst_min_precision.
	(finish_enum): Likewise.
cp/
	* class.c (check_bitfield_decl): Rename min_precision to
	tree_int_cst_min_precision.
	* decl.c (finish_enum): Likewise.
testsuite/
	* gcc.dg/pr11492.c: New.
	* g++.dg/warn/pr11492.C: New.

From-SVN: r141434
This commit is contained in:
Manuel López-Ibáñez 2008-10-29 17:16:46 +00:00
parent 20ded7a68b
commit cdd6a337c0
13 changed files with 121 additions and 48 deletions

View File

@ -1,3 +1,16 @@
2008-10-29 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR 11492
* c-common.c (min_precision): Move to...
* tree.c (tree_int_cst_min_precision): ... to here. Renamed.
* tree.h (tree_int_cst_min_precision): Declare.
* c-common.h (min_precision): Delete declaration.
* fold-const.c (tree_binary_nonnegative_warnv_p): Handle
multiplication of non-negative integer constants.
* c-decl.c (check_bitfield_type_and_width): Rename min_precision to
tree_int_cst_min_precision.
(finish_enum): Likewise.
2008-10-29 Joseph Myers <joseph@codesourcery.com>
PR middle-end/36578

View File

@ -2795,34 +2795,6 @@ c_register_builtin_type (tree type, const char* name)
registered_builtin_types = tree_cons (0, type, registered_builtin_types);
}
/* Return the minimum number of bits needed to represent VALUE in a
signed or unsigned type, UNSIGNEDP says which. */
unsigned int
min_precision (tree value, int unsignedp)
{
int log;
/* If the value is negative, compute its negative minus 1. The latter
adjustment is because the absolute value of the largest negative value
is one larger than the largest positive value. This is equivalent to
a bit-wise negation, so use that operation instead. */
if (tree_int_cst_sgn (value) < 0)
value = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (value), value);
/* Return the number of bits needed, taking into account the fact
that we need one more bit for a signed than unsigned type. */
if (integer_zerop (value))
log = 0;
else
log = tree_floor_log2 (value);
return log + 1 + !unsignedp;
}
/* Print an error message for invalid operands to arith operation
CODE with TYPE0 for operand 0, and TYPE1 for operand 1.

View File

@ -746,7 +746,6 @@ extern tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwis
extern tree shorten_compare (tree *, tree *, tree *, enum tree_code *);
extern tree pointer_int_sum (enum tree_code, tree, tree);
extern unsigned int min_precision (tree, int);
/* Add qualifiers to a type, in the fashion for C. */
extern tree c_build_qualified_type (tree, int);

View File

@ -3869,8 +3869,8 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
{
struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
if (!lt
|| w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
|| w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
|| w < tree_int_cst_min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
|| w < tree_int_cst_min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
warning (0, "%qs is narrower than values of its type", name);
}
}
@ -5866,8 +5866,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
that normally we only go as narrow as int - and signed iff any of
the values are negative. */
unsign = (tree_int_cst_sgn (minnode) >= 0);
precision = MAX (min_precision (minnode, unsign),
min_precision (maxnode, unsign));
precision = MAX (tree_int_cst_min_precision (minnode, unsign),
tree_int_cst_min_precision (maxnode, unsign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{

View File

@ -1,3 +1,10 @@
2008-10-29 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR 11492
* class.c (check_bitfield_decl): Rename min_precision to
tree_int_cst_min_precision.
* decl.c (finish_enum): Likewise.
2008-10-29 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR c++/26997

View File

@ -2728,10 +2728,11 @@ check_bitfield_decl (tree field)
warning (0, "width of %q+D exceeds its type", field);
else if (TREE_CODE (type) == ENUMERAL_TYPE
&& (0 > compare_tree_int (w,
min_precision (TYPE_MIN_VALUE (type),
TYPE_UNSIGNED (type)))
tree_int_cst_min_precision
(TYPE_MIN_VALUE (type),
TYPE_UNSIGNED (type)))
|| 0 > compare_tree_int (w,
min_precision
tree_int_cst_min_precision
(TYPE_MAX_VALUE (type),
TYPE_UNSIGNED (type)))))
warning (0, "%q+D is too small to hold all values of %q#T", field, type);

View File

@ -10967,11 +10967,11 @@ finish_enum (tree enumtype)
/* Compute the number of bits require to represent all values of the
enumeration. We must do this before the type of MINNODE and
MAXNODE are transformed, since min_precision relies on the
TREE_TYPE of the value it is passed. */
MAXNODE are transformed, since tree_int_cst_min_precision relies
on the TREE_TYPE of the value it is passed. */
unsignedp = tree_int_cst_sgn (minnode) >= 0;
lowprec = min_precision (minnode, unsignedp);
highprec = min_precision (maxnode, unsignedp);
lowprec = tree_int_cst_min_precision (minnode, unsignedp);
highprec = tree_int_cst_min_precision (maxnode, unsignedp);
precision = MAX (lowprec, highprec);
if (!fixed_underlying_type_p)

View File

@ -14016,15 +14016,38 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
/* zero_extend(x) * zero_extend(y) is non-negative if x and y are
both unsigned and their total bits is shorter than the result. */
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (op0) == NOP_EXPR
&& TREE_CODE (op1) == NOP_EXPR)
&& (TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == INTEGER_CST)
&& (TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == INTEGER_CST))
{
tree inner1 = TREE_TYPE (TREE_OPERAND (op0, 0));
tree inner2 = TREE_TYPE (TREE_OPERAND (op1, 0));
if (TREE_CODE (inner1) == INTEGER_TYPE && TYPE_UNSIGNED (inner1)
&& TREE_CODE (inner2) == INTEGER_TYPE && TYPE_UNSIGNED (inner2))
return TYPE_PRECISION (inner1) + TYPE_PRECISION (inner2)
< TYPE_PRECISION (type);
tree inner0 = (TREE_CODE (op0) == NOP_EXPR)
? TREE_TYPE (TREE_OPERAND (op0, 0))
: TREE_TYPE (op0);
tree inner1 = (TREE_CODE (op1) == NOP_EXPR)
? TREE_TYPE (TREE_OPERAND (op1, 0))
: TREE_TYPE (op1);
bool unsigned0 = TYPE_UNSIGNED (inner0);
bool unsigned1 = TYPE_UNSIGNED (inner1);
if (TREE_CODE (op0) == INTEGER_CST)
unsigned0 = unsigned0 || tree_int_cst_sgn (op0) >= 0;
if (TREE_CODE (op1) == INTEGER_CST)
unsigned1 = unsigned1 || tree_int_cst_sgn (op1) >= 0;
if (TREE_CODE (inner0) == INTEGER_TYPE && unsigned0
&& TREE_CODE (inner1) == INTEGER_TYPE && unsigned1)
{
unsigned int precision0 = (TREE_CODE (op0) == INTEGER_CST)
? tree_int_cst_min_precision (op0, /*unsignedp=*/true)
: TYPE_PRECISION (inner0);
unsigned int precision1 = (TREE_CODE (op1) == INTEGER_CST)
? tree_int_cst_min_precision (op1, /*unsignedp=*/true)
: TYPE_PRECISION (inner1);
return precision0 + precision1 < TYPE_PRECISION (type);
}
}
return false;

View File

@ -1,3 +1,9 @@
2008-10-29 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR 11492
* gcc.dg/pr11492.c: New.
* g++.dg/warn/pr11492.C: New.
2008-10-29 Joseph Myers <joseph@codesourcery.com>
PR middle-end/36578

View File

@ -0,0 +1,12 @@
// PR11492
// { dg-do compile }
// { dg-options "-Wsign-compare" }
int main( void )
{
unsigned int a;
unsigned char b;
for ( a = 0, b = 2; a > b * 1000; a++ ) /* { dg-bogus "comparison between signed and unsigned integer" } */
{ ; }
return 0;
}

View File

@ -0,0 +1,12 @@
/* PR11492 */
/* { dg-do compile } */
/* { dg-options "-Wsign-compare" } */
int main( void )
{
unsigned int a;
unsigned char b;
for ( a = 0, b = 2; a > b * 1000; a++ ) /* { dg-bogus "comparison between signed and unsigned integer" } */
{ ; }
return 0;
}

View File

@ -5035,6 +5035,33 @@ tree_int_cst_sgn (const_tree t)
return 1;
}
/* Return the minimum number of bits needed to represent VALUE in a
signed or unsigned type, UNSIGNEDP says which. */
unsigned int
tree_int_cst_min_precision (tree value, bool unsignedp)
{
int log;
/* If the value is negative, compute its negative minus 1. The latter
adjustment is because the absolute value of the largest negative value
is one larger than the largest positive value. This is equivalent to
a bit-wise negation, so use that operation instead. */
if (tree_int_cst_sgn (value) < 0)
value = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (value), value);
/* Return the number of bits needed, taking into account the fact
that we need one more bit for a signed than unsigned type. */
if (integer_zerop (value))
log = 0;
else
log = tree_floor_log2 (value);
return log + 1 + !unsignedp;
}
/* Compare two constructor-element-type constants. Return 1 if the lists
are known to be equal; otherwise return 0. */

View File

@ -4022,6 +4022,7 @@ extern HOST_WIDE_INT tree_low_cst (const_tree, int);
extern int tree_int_cst_msb (const_tree);
extern int tree_int_cst_sgn (const_tree);
extern int tree_int_cst_sign_bit (const_tree);
extern unsigned int tree_int_cst_min_precision (tree, bool);
extern bool tree_expr_nonnegative_p (tree);
extern bool tree_expr_nonnegative_warnv_p (tree, bool *);
extern bool may_negate_without_overflow_p (const_tree);