aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-03-01 00:45:26 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-03-01 00:45:26 +0000
commitfc24bee911ea0d941ffcd8a25db91f417e303168 (patch)
tree1ecaf86a03bbbb29554ab3479d70193eb8dbcff0 /gcc/go
parent75c37a6484a9c1212e361b1e959d0639d920780f (diff)
downloadgcc-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.cc25
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);