diff options
Diffstat (limited to 'src/go/types/expr.go')
-rw-r--r-- | src/go/types/expr.go | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/src/go/types/expr.go b/src/go/types/expr.go index b55f51185f..c9a55aa871 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -795,32 +795,48 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { // spec: "The right operand in a shift expression must have integer type // or be an untyped constant representable by a value of type uint." - // Provide a good error message for negative shift counts. + // Check that constants are representable by uint, but do not convert them + // (see also issue #47243). if y.mode == constant_ { + // Provide a good error message for negative shift counts. yval := constant.ToInt(y.val) // consider -1, 1.0, but not -1.1 if yval.Kind() == constant.Int && constant.Sign(yval) < 0 { check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y) x.mode = invalid return } + + if isUntyped(y.typ) { + // Caution: Check for representability here, rather than in the switch + // below, because isInteger includes untyped integers (was bug #43697). + check.representable(y, Typ[Uint]) + if y.mode == invalid { + x.mode = invalid + return + } + } } - // Caution: Check for isUntyped first because isInteger includes untyped - // integers (was bug #43697). - if isUntyped(y.typ) { + // Check that RHS is otherwise at least of integer type. + switch { + case isInteger(y.typ): + if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { + check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y) + x.mode = invalid + return + } + case isUntyped(y.typ): + // This is incorrect, but preserves pre-existing behavior. + // See also bug #47410. check.convertUntyped(y, Typ[Uint]) if y.mode == invalid { x.mode = invalid return } - } else if !isInteger(y.typ) { + default: check.invalidOp(y, _InvalidShiftCount, "shift count %s must be integer", y) x.mode = invalid return - } else if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { - check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y) - x.mode = invalid - return } if x.mode == constant_ { |