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:
parent
d352807578
commit
2f35df8c14
4 changed files with 21 additions and 45 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
11
gcc/testsuite/g++.dg/torture/pr34235.C
Normal file
11
gcc/testsuite/g++.dg/torture/pr34235.C
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue