@@ -770,14 +770,14 @@ func (check *Checker) comparison(x, y *operand, op syntax.Operator) {
770
770
}
771
771
772
772
func (check * Checker ) shift (x , y * operand , e * syntax.Operation , op syntax.Operator ) {
773
- untypedx := isUntyped ( x . typ )
773
+ // TODO(gri) This function seems overly complex. Revisit.
774
774
775
775
var xval constant.Value
776
776
if x .mode == constant_ {
777
777
xval = constant .ToInt (x .val )
778
778
}
779
779
780
- if isInteger (x .typ ) || untypedx && xval != nil && xval .Kind () == constant .Int {
780
+ if isInteger (x .typ ) || isUntyped ( x . typ ) && xval != nil && xval .Kind () == constant .Int {
781
781
// The lhs is of integer type or an untyped constant representable
782
782
// as an integer. Nothing to do.
783
783
} else {
@@ -789,40 +789,36 @@ func (check *Checker) shift(x, y *operand, e *syntax.Operation, op syntax.Operat
789
789
790
790
// spec: "The right operand in a shift expression must have integer type
791
791
// or be an untyped constant representable by a value of type uint."
792
- switch {
793
- case isInteger ( y . typ ):
794
- // nothing to do
795
- case isUntyped (y .typ ):
796
- check . convertUntyped ( y , Typ [ Uint ])
797
- if y . mode == invalid {
792
+
793
+ // Provide a good error message for negative shift counts.
794
+ if y . mode == constant_ {
795
+ yval := constant . ToInt (y .val ) // consider -1, 1.0, but not -1.1
796
+ if yval . Kind () == constant . Int && constant . Sign ( yval ) < 0 {
797
+ check . invalidOpf ( y , "negative shift count %s" , y )
798
798
x .mode = invalid
799
799
return
800
800
}
801
- default :
802
- check .invalidOpf (y , "shift count %s must be integer" , y )
803
- x .mode = invalid
804
- return
805
801
}
806
802
807
- var yval constant.Value
808
- if y .mode == constant_ {
809
- // rhs must be an integer value
810
- // (Either it was of an integer type already, or it was
811
- // untyped and successfully converted to a uint above.)
812
- yval = constant .ToInt (y .val )
813
- assert (yval .Kind () == constant .Int )
814
- if constant .Sign (yval ) < 0 {
815
- check .invalidOpf (y , "negative shift count %s" , y )
803
+ // Caution: Check for isUntyped first because isInteger includes untyped
804
+ // integers (was bug #43697).
805
+ if isUntyped (y .typ ) {
806
+ check .convertUntyped (y , Typ [Uint ])
807
+ if y .mode == invalid {
816
808
x .mode = invalid
817
809
return
818
810
}
811
+ } else if ! isInteger (y .typ ) {
812
+ check .invalidOpf (y , "shift count %s must be integer" , y )
813
+ x .mode = invalid
814
+ return
819
815
}
820
816
821
817
if x .mode == constant_ {
822
818
if y .mode == constant_ {
823
819
// rhs must be within reasonable bounds in constant shifts
824
820
const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64
825
- s , ok := constant .Uint64Val (yval )
821
+ s , ok := constant .Uint64Val (y . val )
826
822
if ! ok || s > shiftBound {
827
823
check .invalidOpf (y , "invalid shift count %s" , y )
828
824
x .mode = invalid
@@ -849,7 +845,7 @@ func (check *Checker) shift(x, y *operand, e *syntax.Operation, op syntax.Operat
849
845
}
850
846
851
847
// non-constant shift with constant lhs
852
- if untypedx {
848
+ if isUntyped ( x . typ ) {
853
849
// spec: "If the left operand of a non-constant shift
854
850
// expression is an untyped constant, the type of the
855
851
// constant is what it would be if the shift expression
0 commit comments