compiler, runtime: implement shifts by signed amounts
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
This commit is contained in:
parent
5ba5ad304a
commit
43055d2379
6 changed files with 43 additions and 12 deletions
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue