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;
{
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)
// 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();
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.
-// errorcheck
+// compile
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
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
}
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));
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");
}