OSDN Git Service

compiler: Fix unary ^ applied to typed signed integer constant.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 1 Mar 2012 00:45:26 +0000 (00:45 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 1 Mar 2012 00:45:26 +0000 (00:45 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184681 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/go/gofrontend/expressions.cc

index 3778c4d..abcd593 100644 (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));
 
          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 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);
          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);
 
 
          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);
          delete[] phwi;
        }
       return Integer_expression::check_constant(val, utype, location);