aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorManuel López-Ibáñez <manu@gcc.gnu.org>2008-10-29 17:16:46 +0000
committerManuel López-Ibáñez <manu@gcc.gnu.org>2008-10-29 17:16:46 +0000
commitcdd6a337c0e1c4a07a0a45686dcaa159e51f451c (patch)
tree42ccc636ef21cba0db86051f05076ac6b24aa628 /gcc
parent20ded7a68b10f9c2d1aaa94e89df494bf0ce41a0 (diff)
downloadgcc-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/ChangeLog13
-rw-r--r--gcc/c-common.c28
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/c-decl.c8
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/class.c7
-rw-r--r--gcc/cp/decl.c8
-rw-r--r--gcc/fold-const.c39
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/warn/pr11492.C12
-rw-r--r--gcc/testsuite/gcc.dg/pr11492.c12
-rw-r--r--gcc/tree.c27
-rw-r--r--gcc/tree.h1
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;
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index 10b50d1..184d247 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 a85b4c6..d85918f 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);