aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2019-08-20 21:15:46 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-08-20 21:15:46 +0000
commit43055d2379cfb1b5b1b09e243a9829e52e12b60a (patch)
tree25ee7c396a4bc315d93ef63cd8092a66275cd5a1 /gcc/go
parent5ba5ad304a16644614c3ea143181682a94cb999e (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc28
-rw-r--r--gcc/go/gofrontend/gogo.h3
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();