diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-08-20 21:15:46 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-08-20 21:15:46 +0000 |
commit | 43055d2379cfb1b5b1b09e243a9829e52e12b60a (patch) | |
tree | 25ee7c396a4bc315d93ef63cd8092a66275cd5a1 /gcc/go | |
parent | 5ba5ad304a16644614c3ea143181682a94cb999e (diff) | |
download | gcc-43055d2379cfb1b5b1b09e243a9829e52e12b60a.zip gcc-43055d2379cfb1b5b1b09e243a9829e52e12b60a.tar.gz gcc-43055d2379cfb1b5b1b09e243a9829e52e12b60a.tar.bz2 |
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
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 28 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.h | 3 |
3 files changed, 27 insertions, 6 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 94bc2f7..2776fb8 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 995a18c..aa0fda0 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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. diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index b3ec629..0abd4b4 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -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(); |