compiler: Fix unary ^ applied to typed signed integer constant.

From-SVN: r184681
This commit is contained in:
Ian Lance Taylor 2012-03-01 00:45:26 +00:00
parent 75c37a6484
commit fc24bee911
1 changed files with 22 additions and 3 deletions

View File

@ -4300,14 +4300,23 @@ Unary_expression::eval_integer(Operator op, Type* utype, mpz_t uval, mpz_t val,
unsigned HOST_WIDE_INT* phwi = new unsigned HOST_WIDE_INT[count];
memset(phwi, 0, count * sizeof(HOST_WIDE_INT));
size_t obits = utype->integer_type()->bits();
if (!utype->integer_type()->is_unsigned()
&& mpz_sgn(uval) < 0)
{
mpz_t adj;
mpz_init_set_ui(adj, 1);
mpz_mul_2exp(adj, adj, obits);
mpz_add(uval, uval, adj);
mpz_clear(adj);
}
size_t ecount;
mpz_export(phwi, &ecount, -1, sizeof(HOST_WIDE_INT), 0, 0, uval);
go_assert(ecount <= count);
// Trim down to the number of words required by the type.
size_t obits = utype->integer_type()->bits();
if (!utype->integer_type()->is_unsigned())
++obits;
size_t ocount = ((obits + HOST_BITS_PER_WIDE_INT - 1)
/ HOST_BITS_PER_WIDE_INT);
go_assert(ocount <= count);
@ -4322,6 +4331,16 @@ Unary_expression::eval_integer(Operator op, Type* utype, mpz_t uval, mpz_t val,
mpz_import(val, ocount, -1, sizeof(HOST_WIDE_INT), 0, 0, phwi);
if (!utype->integer_type()->is_unsigned()
&& mpz_tstbit(val, obits - 1))
{
mpz_t adj;
mpz_init_set_ui(adj, 1);
mpz_mul_2exp(adj, adj, obits);
mpz_sub(val, val, adj);
mpz_clear(adj);
}
delete[] phwi;
}
return Integer_expression::check_constant(val, utype, location);