From e538e1b627d16778134704310f39a1fec997184d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 15 Oct 2015 09:50:40 -0700 Subject: [PATCH] go/types: check that typed constant shift expressions are representable Fixes #12945. Change-Id: I08b44795fcd7ec59371aea8111f7febead54720b Reviewed-on: https://go-review.googlesource.com/15900 Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 12 ++++++++++-- src/go/types/testdata/const1.src | 8 ++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/go/types/expr.go b/src/go/types/expr.go index ce9ea83b97a..387a32fc159 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -618,7 +618,7 @@ func (check *Checker) comparison(x, y *operand, op token.Token) { x.typ = Typ[UntypedBool] } -func (check *Checker) shift(x, y *operand, op token.Token) { +func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { untypedx := isUntyped(x.typ) // The lhs must be of integer type or be representable @@ -671,6 +671,14 @@ func (check *Checker) shift(x, y *operand, op token.Token) { x.typ = Typ[UntypedInt] } x.val = constant.Shift(x.val, op, uint(s)) + // Typed constants must be representable in + // their type after each constant operation. + if isTyped(x.typ) { + if e != nil { + x.expr = e // for better error message + } + check.representable(x, x.typ.Underlying().(*Basic)) + } return } @@ -753,7 +761,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o } if isShift(op) { - check.shift(x, &y, op) + check.shift(x, &y, e, op) return } diff --git a/src/go/types/testdata/const1.src b/src/go/types/testdata/const1.src index 88e9fad3c11..d82770464fa 100644 --- a/src/go/types/testdata/const1.src +++ b/src/go/types/testdata/const1.src @@ -312,3 +312,11 @@ const ( y64 = float64(f64) _ = assert(x64 - y64 == 0) ) + +const ( + _ = int8(-1) << 7 + _ = int8 /* ERROR "overflows" */ (-1) << 8 + + _ = uint32(1) << 31 + _ = uint32 /* ERROR "overflows" */ (1) << 32 +)