go.tools/go/types: added missing implicit conversion checks
R=adonovan, r CC=golang-dev https://golang.org/cl/11934047
This commit is contained in:
parent
41fb587948
commit
4ea4ce9e03
|
|
@ -51,6 +51,7 @@ var tests = [][]string{
|
||||||
{"testdata/decls2a.src", "testdata/decls2b.src"},
|
{"testdata/decls2a.src", "testdata/decls2b.src"},
|
||||||
{"testdata/decls3.src"},
|
{"testdata/decls3.src"},
|
||||||
{"testdata/const0.src"},
|
{"testdata/const0.src"},
|
||||||
|
{"testdata/const1.src"},
|
||||||
{"testdata/constdecl.src"},
|
{"testdata/constdecl.src"},
|
||||||
{"testdata/vardecl.src"},
|
{"testdata/vardecl.src"},
|
||||||
{"testdata/expr0.src"},
|
{"testdata/expr0.src"},
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ package types
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"math"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/go/exact"
|
"code.google.com/p/go.tools/go/exact"
|
||||||
)
|
)
|
||||||
|
|
@ -155,6 +156,19 @@ func isComparison(op token.Token) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fitsFloat32(x exact.Value) bool {
|
||||||
|
f, _ := exact.Float64Val(x)
|
||||||
|
// We assume that float32(f) returns an Inf if f
|
||||||
|
// cannot be represented as a float32, or if f
|
||||||
|
// is an Inf. This is not supported by the spec.
|
||||||
|
return !math.IsInf(float64(float32(f)), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fitsFloat64(x exact.Value) bool {
|
||||||
|
f, _ := exact.Float64Val(x)
|
||||||
|
return !math.IsInf(f, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
|
func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
|
||||||
switch x.Kind() {
|
switch x.Kind() {
|
||||||
case exact.Unknown:
|
case exact.Unknown:
|
||||||
|
|
@ -196,15 +210,8 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
|
||||||
return 0 <= x && x <= 1<<s-1
|
return 0 <= x && x <= 1<<s-1
|
||||||
case Uint64:
|
case Uint64:
|
||||||
return 0 <= x
|
return 0 <= x
|
||||||
case Float32:
|
case Float32, Float64, Complex64, Complex128,
|
||||||
return true // TODO(gri) fix this
|
UntypedInt, UntypedFloat, UntypedComplex:
|
||||||
case Float64:
|
|
||||||
return true // TODO(gri) fix this
|
|
||||||
case Complex64:
|
|
||||||
return true // TODO(gri) fix this
|
|
||||||
case Complex128:
|
|
||||||
return true // TODO(gri) fix this
|
|
||||||
case UntypedInt, UntypedFloat, UntypedComplex:
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -216,28 +223,20 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
|
||||||
return exact.Sign(x) >= 0 && n <= int(s)
|
return exact.Sign(x) >= 0 && n <= int(s)
|
||||||
case Uint64:
|
case Uint64:
|
||||||
return exact.Sign(x) >= 0 && n <= 64
|
return exact.Sign(x) >= 0 && n <= 64
|
||||||
case Float32:
|
case Float32, Complex64:
|
||||||
return true // TODO(gri) fix this
|
return fitsFloat32(x)
|
||||||
case Float64:
|
case Float64, Complex128:
|
||||||
return true // TODO(gri) fix this
|
return fitsFloat64(x)
|
||||||
case Complex64:
|
|
||||||
return true // TODO(gri) fix this
|
|
||||||
case Complex128:
|
|
||||||
return true // TODO(gri) fix this
|
|
||||||
case UntypedInt, UntypedFloat, UntypedComplex:
|
case UntypedInt, UntypedFloat, UntypedComplex:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
case exact.Float:
|
case exact.Float:
|
||||||
switch as {
|
switch as {
|
||||||
case Float32:
|
case Float32, Complex64:
|
||||||
return true // TODO(gri) fix this
|
return fitsFloat32(x)
|
||||||
case Float64:
|
case Float64, Complex128:
|
||||||
return true // TODO(gri) fix this
|
return fitsFloat64(x)
|
||||||
case Complex64:
|
|
||||||
return true // TODO(gri) fix this
|
|
||||||
case Complex128:
|
|
||||||
return true // TODO(gri) fix this
|
|
||||||
case UntypedFloat, UntypedComplex:
|
case UntypedFloat, UntypedComplex:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -245,9 +244,9 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
|
||||||
case exact.Complex:
|
case exact.Complex:
|
||||||
switch as {
|
switch as {
|
||||||
case Complex64:
|
case Complex64:
|
||||||
return true // TODO(gri) fix this
|
return fitsFloat32(exact.Real(x)) && fitsFloat32(exact.Imag(x))
|
||||||
case Complex128:
|
case Complex128:
|
||||||
return true // TODO(gri) fix this
|
return fitsFloat64(exact.Real(x)) && fitsFloat64(exact.Imag(x))
|
||||||
case UntypedComplex:
|
case UntypedComplex:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -540,9 +539,9 @@ func (check *checker) shift(x, y *operand, op token.Token) {
|
||||||
if x.mode == constant {
|
if x.mode == constant {
|
||||||
if y.mode == constant {
|
if y.mode == constant {
|
||||||
// rhs must be within reasonable bounds
|
// rhs must be within reasonable bounds
|
||||||
const stupidShift = 1024
|
const stupidShift = 1023 - 1 + 52 // so we can express smallestFloat64
|
||||||
s, ok := exact.Uint64Val(y.val)
|
s, ok := exact.Uint64Val(y.val)
|
||||||
if !ok || s >= stupidShift {
|
if !ok || s > stupidShift {
|
||||||
check.invalidOp(y.pos(), "%s: stupid shift", y)
|
check.invalidOp(y.pos(), "%s: stupid shift", y)
|
||||||
x.mode = invalid
|
x.mode = invalid
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,157 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// implicit constant conversions
|
||||||
|
|
||||||
|
package const1
|
||||||
|
|
||||||
|
// TODO(gri) add int/uint/uintptr sizes and tests
|
||||||
|
|
||||||
|
const (
|
||||||
|
minInt8 = -1<<(8<<iota - 1)
|
||||||
|
minInt16
|
||||||
|
minInt32
|
||||||
|
minInt64
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxInt8 = 1<<(8<<iota - 1) - 1
|
||||||
|
maxInt16
|
||||||
|
maxInt32
|
||||||
|
maxInt64
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxUint8 = 1<<(8<<iota) - 1
|
||||||
|
maxUint16
|
||||||
|
maxUint32
|
||||||
|
maxUint64
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
smallestFloat32 = 1.0 / (1<<(127 - 1 + 23))
|
||||||
|
smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ = assert(smallestFloat32 > 0)
|
||||||
|
_ = assert(smallestFloat64 > 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxFloat32 = 1<<127 * (1<<24 - 1) / (1.0<<23)
|
||||||
|
maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ int8 = minInt8 /* ERROR "overflows" */ - 1
|
||||||
|
_ int8 = minInt8
|
||||||
|
_ int8 = maxInt8
|
||||||
|
_ int8 = maxInt8 /* ERROR "overflows" */ + 1
|
||||||
|
_ int8 = smallestFloat64 /* ERROR "overflows" */
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ int16 = minInt16 /* ERROR "overflows" */ - 1
|
||||||
|
_ int16 = minInt16
|
||||||
|
_ int16 = maxInt16
|
||||||
|
_ int16 = maxInt16 /* ERROR "overflows" */ + 1
|
||||||
|
_ int16 = smallestFloat64 /* ERROR "overflows" */
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ int32 = minInt32 /* ERROR "overflows" */ - 1
|
||||||
|
_ int32 = minInt32
|
||||||
|
_ int32 = maxInt32
|
||||||
|
_ int32 = maxInt32 /* ERROR "overflows" */ + 1
|
||||||
|
_ int32 = smallestFloat64 /* ERROR "overflows" */
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ int64 = minInt64 /* ERROR "overflows" */ - 1
|
||||||
|
_ int64 = minInt64
|
||||||
|
_ int64 = maxInt64
|
||||||
|
_ int64 = maxInt64 /* ERROR "overflows" */ + 1
|
||||||
|
_ int64 = smallestFloat64 /* ERROR "overflows" */
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ uint8 = 0 /* ERROR "overflows" */ - 1
|
||||||
|
_ uint8 = 0
|
||||||
|
_ uint8 = maxUint8
|
||||||
|
_ uint8 = maxUint8 /* ERROR "overflows" */ + 1
|
||||||
|
_ uint8 = smallestFloat64 /* ERROR "overflows" */
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ uint16 = 0 /* ERROR "overflows" */ - 1
|
||||||
|
_ uint16 = 0
|
||||||
|
_ uint16 = maxUint16
|
||||||
|
_ uint16 = maxUint16 /* ERROR "overflows" */ + 1
|
||||||
|
_ uint16 = smallestFloat64 /* ERROR "overflows" */
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ uint32 = 0 /* ERROR "overflows" */ - 1
|
||||||
|
_ uint32 = 0
|
||||||
|
_ uint32 = maxUint32
|
||||||
|
_ uint32 = maxUint32 /* ERROR "overflows" */ + 1
|
||||||
|
_ uint32 = smallestFloat64 /* ERROR "overflows" */
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ uint64 = 0 /* ERROR "overflows" */ - 1
|
||||||
|
_ uint64 = 0
|
||||||
|
_ uint64 = maxUint64
|
||||||
|
_ uint64 = maxUint64 /* ERROR "overflows" */ + 1
|
||||||
|
_ uint64 = smallestFloat64 /* ERROR "overflows" */
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ float32 = minInt64
|
||||||
|
_ float64 = minInt64
|
||||||
|
_ complex64 = minInt64
|
||||||
|
_ complex128 = minInt64
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ float32 = maxUint64
|
||||||
|
_ float64 = maxUint64
|
||||||
|
_ complex64 = maxUint64
|
||||||
|
_ complex128 = maxUint64
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(gri) find smaller deltas below
|
||||||
|
|
||||||
|
const delta32 = maxFloat32 >> 23
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ float32 = - /* ERROR "overflow" */ (maxFloat32 + delta32)
|
||||||
|
_ float32 = -maxFloat32
|
||||||
|
_ float32 = maxFloat32
|
||||||
|
_ float32 = maxFloat32 /* ERROR "overflow" */ + delta32
|
||||||
|
)
|
||||||
|
|
||||||
|
const delta64 = maxFloat64 >> 52
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ float64 = - /* ERROR "overflow" */ (maxFloat64 + delta64)
|
||||||
|
_ float64 = -maxFloat64
|
||||||
|
_ float64 = maxFloat64
|
||||||
|
_ float64 = maxFloat64 /* ERROR "overflow" */ + delta64
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ complex64 = - /* ERROR "overflow" */ (maxFloat32 + delta32)
|
||||||
|
_ complex64 = -maxFloat32
|
||||||
|
_ complex64 = maxFloat32
|
||||||
|
_ complex64 = maxFloat32 /* ERROR "overflow" */ + delta32
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ complex128 = - /* ERROR "overflow" */ (maxFloat64 + delta64)
|
||||||
|
_ complex128 = -maxFloat64
|
||||||
|
_ complex128 = maxFloat64
|
||||||
|
_ complex128 = maxFloat64 /* ERROR "overflow" */ + delta64
|
||||||
|
)
|
||||||
|
|
@ -15,7 +15,7 @@ func shifts1() {
|
||||||
v2 = 1<<u0
|
v2 = 1<<u0
|
||||||
v3 = 1<<"foo" /* ERROR "cannot convert" */
|
v3 = 1<<"foo" /* ERROR "cannot convert" */
|
||||||
v4 = 1<<- /* ERROR "stupid shift" */ 1
|
v4 = 1<<- /* ERROR "stupid shift" */ 1
|
||||||
v5 = 1<<1025 /* ERROR "stupid shift" */
|
v5 = 1<<1075 /* ERROR "stupid shift" */
|
||||||
v6 = 1 /* ERROR "overflows" */ <<100
|
v6 = 1 /* ERROR "overflows" */ <<100
|
||||||
|
|
||||||
v10 uint = 1 << 0
|
v10 uint = 1 << 0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue