From cdd6a337c0e1c4a07a0a45686dcaa159e51f451c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20L=C3=B3pez-Ib=C3=A1=C3=B1ez?= Date: Wed, 29 Oct 2008 17:16:46 +0000 Subject: [PATCH] re PR middle-end/11492 (Bogus warning with -Wsign-compare) 2008-10-29 Manuel Lopez-Ibanez 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 --- gcc/ChangeLog | 13 ++++++++++ gcc/c-common.c | 28 --------------------- gcc/c-common.h | 1 - gcc/c-decl.c | 8 +++--- gcc/cp/ChangeLog | 7 ++++++ gcc/cp/class.c | 7 +++--- gcc/cp/decl.c | 8 +++--- gcc/fold-const.c | 39 +++++++++++++++++++++++------ gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/g++.dg/warn/pr11492.C | 12 +++++++++ gcc/testsuite/gcc.dg/pr11492.c | 12 +++++++++ gcc/tree.c | 27 ++++++++++++++++++++ gcc/tree.h | 1 + 13 files changed, 121 insertions(+), 48 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/pr11492.C create mode 100644 gcc/testsuite/gcc.dg/pr11492.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1270ebc5f28..dc5ab3be569 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2008-10-29 Manuel Lopez-Ibanez + + 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 PR middle-end/36578 diff --git a/gcc/c-common.c b/gcc/c-common.c index 30acb7d0a43..84dea11491b 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 be38a60e54d..dc5da719c9b 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 eba616199b6..6f88f626042 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 5115c1b6237..8370307aaaa 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2008-10-29 Manuel Lopez-Ibanez + + 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 PR c++/26997 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 910dc291f8e..31123aa1ffd 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 b0b03a549e6..c9cac551a55 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 7a215d27cb4..1a96c3f77fc 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 6e3f6f2123e..cee6d6ca319 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-10-29 Manuel Lopez-Ibanez + + PR 11492 + * gcc.dg/pr11492.c: New. + * g++.dg/warn/pr11492.C: New. + 2008-10-29 Joseph Myers 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 00000000000..d23595f2d58 --- /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 00000000000..9d79f45b92d --- /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; +} diff --git a/gcc/tree.c b/gcc/tree.c index 10b50d121dc..184d2471744 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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. */ diff --git a/gcc/tree.h b/gcc/tree.h index a85b4c6dbb1..d85918fae1f 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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);