compiler, runtime: implement shifts by signed amounts
authorIan Lance Taylor <iant@golang.org>
Tue, 20 Aug 2019 21:15:46 +0000 (21:15 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 20 Aug 2019 21:15:46 +0000 (21:15 +0000)
    Shifting by signed types is a new language feature in Go 1.13.

    This requires a patch to the testsuite.

    Updates golang/go#19113

    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/190977

* go.test/test/fixedbugs/bug073.go: Update for language changes.

From-SVN: r274755

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo.h
gcc/testsuite/ChangeLog
gcc/testsuite/go.test/test/fixedbugs/bug073.go
libgo/runtime/go-runtime-error.c

index 94bc2f7c0841c0662b4ef4708ebeac88df367797..2776fb80224e2ef1235544d7de79950db2b4716b 100644 (file)
@@ -1,4 +1,4 @@
-a453eebae76296a39a1ded5bd2bffa78bedf40bd
+1846b07fec2b91facc02ea269f7ab250b30f90b4
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 995a18c71b84656e2975fd9997a8270aa8a5c839..aa0fda091bd374c76d441276b29074f3b25949c1 100644 (file)
@@ -6734,11 +6734,10 @@ Binary_expression::do_check_types(Gogo*)
        this->report_error(_("shift of non-integer operand"));
 
       if (right_type->is_string_type())
-        this->report_error(_("shift count not unsigned integer"));
+        this->report_error(_("shift count not integer"));
       else if (!right_type->is_abstract()
-         && (right_type->integer_type() == NULL
-             || !right_type->integer_type()->is_unsigned()))
-       this->report_error(_("shift count not unsigned integer"));
+              && right_type->integer_type() == NULL)
+       this->report_error(_("shift count not integer"));
       else
        {
          Numeric_constant nc;
@@ -6746,7 +6745,7 @@ Binary_expression::do_check_types(Gogo*)
            {
              mpz_t val;
              if (!nc.to_int(&val))
-               this->report_error(_("shift count not unsigned integer"));
+               this->report_error(_("shift count not integer"));
              else
                {
                  if (mpz_sgn(val) < 0)
@@ -6865,9 +6864,11 @@ Binary_expression::do_get_backend(Translate_context* context)
 
   // In Go, a shift larger than the size of the type is well-defined.
   // This is not true in C, so we need to insert a conditional.
+  // We also need to check for a negative shift count.
   if (is_shift_op)
     {
       go_assert(left_type->integer_type() != NULL);
+      go_assert(right_type->integer_type() != NULL);
 
       int bits = left_type->integer_type()->bits();
 
@@ -6909,6 +6910,23 @@ Binary_expression::do_get_backend(Translate_context* context)
                                                        ret, overflow, loc);
          mpz_clear(bitsval);
        }
+
+      if (!right_type->integer_type()->is_unsigned()
+         && (!this->right_->numeric_constant_value(&nc)
+             || nc.to_unsigned_long(&ul) != Numeric_constant::NC_UL_VALID))
+       {
+         Bexpression* zero_expr =
+           gogo->backend()->integer_constant_expression(right_btype, zero);
+         Bexpression* compare =
+           gogo->backend()->binary_expression(OPERATOR_LT, right, zero_expr,
+                                              loc);
+         const int errcode = RUNTIME_ERROR_SHIFT_BY_NEGATIVE;
+         Bexpression* crash =
+           gogo->runtime_error(errcode, loc)->get_backend(context);
+         Bfunction* bfn = context->function()->func_value()->get_decl();
+         ret = gogo->backend()->conditional_expression(bfn, btype, compare,
+                                                       crash, ret, loc);
+       }
     }
 
   // Add checks for division by zero and division overflow as needed.
index b3ec6291d32aebeec00c23fa618540e71c3a15c5..0abd4b4cb2a5de29c19294e9d24b315ba07faf54 100644 (file)
@@ -3745,6 +3745,9 @@ static const int RUNTIME_ERROR_DIVISION_BY_ZERO = 11;
 // Go statement with nil function.
 static const int RUNTIME_ERROR_GO_NIL = 12;
 
+// Shift by negative value.
+static const int RUNTIME_ERROR_SHIFT_BY_NEGATIVE = 13;
+
 // This is used by some of the langhooks.
 extern Gogo* go_get_gogo();
 
index 0512a60019d5e389a98db5e5b12119835ccc271c..2e361d303503e74308b85637015fbeeb7582a214 100644 (file)
@@ -1,3 +1,7 @@
+2019-08-20  Ian Lance Taylor  <iant@golang.org>
+
+       * go.test/test/fixedbugs/bug073.go: Update for language changes.
+
 2019-08-20  Matthew Beliveau  <mbelivea@redhat.com>
 
        * gcc.dg/tree-ssa/redundant-assign-zero-1.c: New test.
index 49b47ae464915450aeedda0a32ede85b96e831a4..f3605b37cfe6df8d99182679c7a1077a93e7a127 100644 (file)
@@ -1,4 +1,4 @@
-// errorcheck
+// compile
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -7,8 +7,8 @@
 package main
 
 func main() {
-       var s int = 0;
-       var x int = 0;
-       x = x << s;  // ERROR "illegal|inval|shift"
-       x = x >> s;  // ERROR "illegal|inval|shift"
+       var s int = 0
+       var x int = 0
+       x = x << s // as of 1.13, these are ok
+       x = x >> s // as of 1.13, these are ok
 }
index c9ccf98736f7d142f049d66a6da6688bd3bdec10..8179e685ef785c065d6721860f16dae206c17970 100644 (file)
@@ -55,7 +55,10 @@ enum
   DIVISION_BY_ZERO = 11,
 
   /* Go statement with nil function.  */
-  GO_NIL = 12
+  GO_NIL = 12,
+
+  /* Shift by negative value.  */
+  SHIFT_BY_NEGATIVE = 13
 };
 
 extern void __go_runtime_error (int32) __attribute__ ((noreturn));
@@ -112,6 +115,9 @@ __go_runtime_error (int32 i)
       runtime_g()->m->throwing = -1;
       runtime_throw ("go of nil func value");
 
+    case SHIFT_BY_NEGATIVE:
+      runtime_panicstring ("negative shift amount");
+
     default:
       runtime_panicstring ("unknown runtime error");
     }