Consider this sample code: x = foo[i];
when pointers are larger than integers and size_t [*], we compute the offset (i) and extend it to pointer size. However, there's no check to see if a sign or zero extension should be used. If the offset is unsigned (say, i is "unsigned int") it sign extends it anyway, resulting in an incorrect offset. Does it make sense to check for signed vs unsigned offsets and pass the right flag to convert_to_mode? This results in smaller code on m32c, where HI moves to address registers (PSI) are zero extended. Alternately, we should at least use the POINTERS_EXTEND_UNSIGNED *value* in convert_to_mode. [*] There aren't any pointer-sized math operations on m32c, just SI and HI sized ones. Pointers are 24 bits. Thus, pointers and addresses are 24 bits, but no single data item can exceed 64k, so offsets are 16 bits. Index: expr.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/expr.c,v retrieving revision 1.814 diff -p -U3 -r1.814 expr.c --- expr.c 1 Sep 2005 01:06:45 -0000 1.814 +++ expr.c 2 Sep 2005 05:01:10 -0000 @@ -7210,6 +7210,7 @@ expand_expr_real_1 (tree exp, rtx target if (offset != 0) { + int unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset)); rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM); @@ -7217,10 +7218,10 @@ expand_expr_real_1 (tree exp, rtx target #ifdef POINTERS_EXTEND_UNSIGNED if (GET_MODE (offset_rtx) != Pmode) - offset_rtx = convert_to_mode (Pmode, offset_rtx, 0); + offset_rtx = convert_to_mode (Pmode, offset_rtx, unsigned_p); #else if (GET_MODE (offset_rtx) != ptr_mode) - offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0); + offset_rtx = convert_to_mode (ptr_mode, offset_rtx, unsigned_p); #endif if (GET_MODE (op0) == BLKmode