diff options
author | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2008-10-29 17:16:46 +0000 |
---|---|---|
committer | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2008-10-29 17:16:46 +0000 |
commit | cdd6a337c0e1c4a07a0a45686dcaa159e51f451c (patch) | |
tree | 42ccc636ef21cba0db86051f05076ac6b24aa628 /gcc | |
parent | 20ded7a68b10f9c2d1aaa94e89df494bf0ce41a0 (diff) | |
download | gcc-cdd6a337c0e1c4a07a0a45686dcaa159e51f451c.zip gcc-cdd6a337c0e1c4a07a0a45686dcaa159e51f451c.tar.gz gcc-cdd6a337c0e1c4a07a0a45686dcaa159e51f451c.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/c-common.c | 28 | ||||
-rw-r--r-- | gcc/c-common.h | 1 | ||||
-rw-r--r-- | gcc/c-decl.c | 8 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/class.c | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 8 | ||||
-rw-r--r-- | gcc/fold-const.c | 39 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/pr11492.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr11492.c | 12 | ||||
-rw-r--r-- | gcc/tree.c | 27 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
13 files changed, 121 insertions, 48 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1270ebc..dc5ab3b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/c-common.c b/gcc/c-common.c index 30acb7d..84dea11 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -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. diff --git a/gcc/c-common.h b/gcc/c-common.h index be38a60..dc5da71 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -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); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index eba6161..6f88f62 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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)) { diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5115c1b..8370307 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 910dc29..31123aa 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b0b03a5..c9cac55 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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) diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 7a215d2..1a96c3f 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6e3f6f2..cee6d6c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/warn/pr11492.C b/gcc/testsuite/g++.dg/warn/pr11492.C new file mode 100644 index 0000000..d23595f --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/pr11492.C @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/pr11492.c b/gcc/testsuite/gcc.dg/pr11492.c new file mode 100644 index 0000000..9d79f45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr11492.c @@ -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; +} @@ -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. */ @@ -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); |