// Uint64 returns the numeric value of this literal truncated to fit // an unsigned 64-bit integer. // func (l *Literal) Uint64() uint64 { switch x := l.Value; x.Kind() { case exact.Int: if u, ok := exact.Uint64Val(x); ok { return u } return 0 case exact.Float: f, _ := exact.Float64Val(x) return uint64(f) } panic(fmt.Sprintf("unexpected literal value: %T", l.Value)) }
func (check *checker) shift(x, y *operand, op token.Token) { untypedx := isUntyped(x.typ) // The lhs must be of integer type or be representable // as an integer; otherwise the shift has no chance. if !isInteger(x.typ) && (!untypedx || !isRepresentableConst(x.val, nil, UntypedInt)) { check.invalidOp(x.pos(), "shifted operand %s must be integer", x) x.mode = invalid return } // spec: "The right operand in a shift expression must have unsigned // integer type or be an untyped constant that can be converted to // unsigned integer type." switch { case isInteger(y.typ) && isUnsigned(y.typ): // nothing to do case isUntyped(y.typ): check.convertUntyped(y, Typ[UntypedInt]) if y.mode == invalid { x.mode = invalid return } default: check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y) x.mode = invalid return } if x.mode == constant { if y.mode == constant { if untypedx { x.typ = Typ[UntypedInt] } // rhs must be within reasonable bounds const stupidShift = 1024 s, ok := exact.Uint64Val(y.val) if !ok || s >= stupidShift { check.invalidOp(y.pos(), "%s: stupid shift", y) x.mode = invalid return } // everything's ok x.val = exact.Shift(x.val, op, uint(s)) return } // non-constant shift with constant lhs if untypedx { // spec: "If the left operand of a non-constant shift expression is // an untyped constant, the type of the constant is what it would be // if the shift expression were replaced by its left operand alone; // the type is int if it cannot be determined from the context (for // instance, if the shift expression is an operand in a comparison // against an untyped constant)". // Delay operand checking until we know the final type: // The lhs expression must be in the untyped map, mark // the entry as lhs shift operand. if info, ok := check.untyped[x.expr]; ok { info.isLhs = true check.untyped[x.expr] = info } else { unreachable() } // keep x's type x.mode = value return } } // non-constant shift - lhs must be an integer if !isInteger(x.typ) { check.invalidOp(x.pos(), "shifted operand %s must be integer", x) x.mode = invalid return } // non-constant shift x.mode = value }