re PR c++/34235 (short variable cast to unsigned int fails to right shift as unsigned)

2008-01-26  Richard Guenther  <rguenther@suse.de>

	PR c++/34235
	* typeck.c (build_binary_op): Remove code to shorten compares.

	* g++.dg/torture/pr34235.C: New testcase.

From-SVN: r131862
This commit is contained in:
Richard Guenther 2008-01-26 11:26:36 +00:00 committed by Richard Biener
parent d352807578
commit 2f35df8c14
4 changed files with 21 additions and 45 deletions

View file

@ -1,3 +1,8 @@
2008-01-26 Richard Guenther <rguenther@suse.de>
PR c++/34235
* typeck.c (build_binary_op): Remove code to shorten compares.
2008-01-25 Richard Guenther <rguenther@suse.de>
PR c++/33887

View file

@ -3065,10 +3065,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
Also implies COMMON. */
int short_compare = 0;
/* Nonzero if this is a right-shift operation, which can be computed on the
original short and then promoted if the operand is a promoted short. */
int short_shift = 0;
/* Nonzero means set RESULT_TYPE to the common type of the args. */
int common = 0;
@ -3270,8 +3266,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
warning (0, "right shift count is negative");
else
{
if (! integer_zerop (op1))
short_shift = 1;
if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
warning (0, "right shift count >= width of type");
}
@ -3686,45 +3680,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
result_type = type;
}
/* Shifts can be shortened if shifting right. */
if (short_shift)
{
int unsigned_arg;
tree arg0 = get_narrower (op0, &unsigned_arg);
final_type = result_type;
if (arg0 == op0 && final_type == TREE_TYPE (op0))
unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
/* We can shorten only if the shift count is less than the
number of bits in the smaller type size. */
&& compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
/* If arg is sign-extended and then unsigned-shifted,
we can simulate this with a signed shift in arg's type
only if the extended result is at least twice as wide
as the arg. Otherwise, the shift could use up all the
ones made by sign-extension and bring in zeros.
We can't optimize that case at all, but in most machines
it never happens because available widths are 2**N. */
&& (!TYPE_UNSIGNED (final_type)
|| unsigned_arg
|| (((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0)))
<= TYPE_PRECISION (result_type))))
{
/* Do an unsigned shift if the operand was zero-extended. */
result_type
= c_common_signed_or_unsigned_type (unsigned_arg,
TREE_TYPE (arg0));
/* Convert value-to-be-shifted to that type. */
if (TREE_TYPE (op0) != result_type)
op0 = cp_convert (result_type, op0);
converted = 1;
}
}
/* Comparison operations are shortened too but differently.
They identify themselves by setting short_compare = 1. */

View file

@ -1,3 +1,8 @@
2008-01-26 Richard Guenther <rguenther@suse.de>
PR c++/34235
* g++.dg/torture/pr34235.C: New testcase.
2008-01-26 Richard Sandiford <rsandifo@nildram.co.uk>
* g++.dg/tree-ssa/ivopts-1.C: XFAIL for MIPS too.

View file

@ -0,0 +1,11 @@
/* { dg-do run } */
extern "C" void abort (void);
int main()
{
short x = -1;
unsigned int c = ((unsigned int)x) >> 1;
if (c != 0x7fffffff)
abort();
return 0;
}