This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch to elide more signed/unsigned warnings
- To: gcc-patches at gcc dot gnu dot org
- Subject: Patch to elide more signed/unsigned warnings
- From: "Kaveh R. Ghazi" <ghazi at caip dot rutgers dot edu>
- Date: Wed, 22 Aug 2001 21:33:43 -0400 (EDT)
I recently looked at some signed/unsigned warnings in gcc.
calls.c:923: warning: comparison between signed and unsigned
calls.c:923: warning: signed and unsigned type in conditional expression
calls.c:3873: warning: comparison between signed and unsigned
calls.c:3873: warning: signed and unsigned type in conditional expression
They arise from code like this:
MIN (GET_MODE_SIZE (save_mode), BIGGEST_ALIGNMENT / UNITS_PER_WORD)
On Solaris 2.7 it expands to this fun expression:
(((mode_size[(int)(save_mode)]))<((target_flags&0x10000)?128:64)?((mode_size[(int)(save_mode)])):(((!(!(target_flags&0x10000)))?128:64)/((!(!(target_flags&0x10000)))?8:4)))
GCC should be able to determine that the various operands of the
complete expression are non-negative, thus the whole thing is. The
missing bit of smarts is division. E.g.:
non-neg-expr1 / non-neg-expr2
So I added handling of *_DIV_EXPR (and while at it *_MOD_EXPR) to
tree_expr_nonnegative_p. I think in C its only the TRUNC variation,
but I did all of them anyway. For DIV, its non-neg if both operands
are so, for MOD, its non-neg if the first operand is.
In the process, I found out that I needed to also handle SAVE_EXPR and
NON_LVALUE_EXPR cause gcc transforms the original expressions a bit.
I set both of them to non-neg if the first operand is.
Bootstrapped on solaris2.7 with c,c++,f77. (Objc is broken at the
moment.) No regressions and the new testcase passes.
Okay to install?
--Kaveh
2001-08-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* fold-const.c (tree_expr_nonnegative_p): Handle *_DIV_EXPR,
*_MOD_EXPR, SAVE_EXPR and NON_LVALUE_EXPR.
testsuite:
* gcc.dg/compare5.c: New testcase.
diff -rup orig/egcs-CVS20010821/gcc/fold-const.c egcs-CVS20010821/gcc/fold-const.c
--- orig/egcs-CVS20010821/gcc/fold-const.c Sat Aug 11 21:56:16 2001
+++ egcs-CVS20010821/gcc/fold-const.c Tue Aug 21 18:28:19 2001
@@ -7397,6 +7397,17 @@ tree_expr_nonnegative_p (t)
return 1;
case INTEGER_CST:
return tree_int_cst_sgn (t) >= 0;
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case TRUNC_MOD_EXPR:
+ case CEIL_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
case COND_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
&& tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
@@ -7412,6 +7423,10 @@ tree_expr_nonnegative_p (t)
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case BIND_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case SAVE_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ case NON_LVALUE_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
case RTL_EXPR:
return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
diff -rup orig/egcs-CVS20010821/gcc/testsuite/gcc.dg/compare5.c egcs-CVS20010821/gcc/testsuite/gcc.dg/compare5.c
--- orig/egcs-CVS20010821/gcc/testsuite/gcc.dg/compare5.c Tue Aug 21 18:30:55 2001
+++ egcs-CVS20010821/gcc/testsuite/gcc.dg/compare5.c Tue Aug 21 18:31:44 2001
@@ -0,0 +1,41 @@
+/* Test for a bogus warning on comparison between signed and unsigned.
+ Origin: Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 8/21/2001. */
+
+/* { dg-do compile } */
+/* { dg-options "-Wsign-compare" } */
+
+extern void bar(void);
+
+int foo(int x, int y, unsigned u)
+{
+ /* A *_DIV_EXPR is non-negative if both operands are. */
+
+ if (u < ((x=-22)/33)) /* { dg-warning "signed and unsigned" "DIV_EXPR" } */
+ return x;
+
+ if (u < ((x=22)/33))
+ return x;
+
+ if (u < ((x=22)/(y=33)))
+ return x;
+
+ if (u < (((x&0x10000)?128:64) / ((y&0x10000)?8:4)))
+ return x;
+
+
+ /* A *_MOD_EXPR is non-negative if the first operand is. */
+
+ if (u < ((x=-22)%33)) /* { dg-warning "signed and unsigned" "MOD_EXPR" } */
+ return x;
+
+ if (u < ((x=22)%-33))
+ return x;
+
+ if (u < ((x==y)%-33))
+ return x;
+
+ if (u < (((x=22)/33)%-33))
+ return x;
+
+ return 0;
+}