diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-03-01 00:45:26 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-03-01 00:45:26 +0000 |
commit | fc24bee911ea0d941ffcd8a25db91f417e303168 (patch) | |
tree | 1ecaf86a03bbbb29554ab3479d70193eb8dbcff0 /gcc/go | |
parent | 75c37a6484a9c1212e361b1e959d0639d920780f (diff) | |
download | gcc-fc24bee911ea0d941ffcd8a25db91f417e303168.zip gcc-fc24bee911ea0d941ffcd8a25db91f417e303168.tar.gz gcc-fc24bee911ea0d941ffcd8a25db91f417e303168.tar.bz2 |
compiler: Fix unary ^ applied to typed signed integer constant.
From-SVN: r184681
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 3778c4d..abcd593 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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); |