mirror of
https://github.com/golang/go
synced 2024-11-18 19:14:40 -07:00
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/decls3.src"},
|
||||
{"testdata/const0.src"},
|
||||
{"testdata/const1.src"},
|
||||
{"testdata/constdecl.src"},
|
||||
{"testdata/vardecl.src"},
|
||||
{"testdata/expr0.src"},
|
||||
|
@ -9,6 +9,7 @@ package types
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"math"
|
||||
|
||||
"code.google.com/p/go.tools/go/exact"
|
||||
)
|
||||
@ -155,6 +156,19 @@ func isComparison(op token.Token) bool {
|
||||
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 {
|
||||
switch x.Kind() {
|
||||
case exact.Unknown:
|
||||
@ -196,15 +210,8 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
|
||||
return 0 <= x && x <= 1<<s-1
|
||||
case Uint64:
|
||||
return 0 <= x
|
||||
case Float32:
|
||||
return true // TODO(gri) fix this
|
||||
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:
|
||||
case Float32, Float64, Complex64, Complex128,
|
||||
UntypedInt, UntypedFloat, UntypedComplex:
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -216,28 +223,20 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
|
||||
return exact.Sign(x) >= 0 && n <= int(s)
|
||||
case Uint64:
|
||||
return exact.Sign(x) >= 0 && n <= 64
|
||||
case Float32:
|
||||
return true // TODO(gri) fix this
|
||||
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 Float32, Complex64:
|
||||
return fitsFloat32(x)
|
||||
case Float64, Complex128:
|
||||
return fitsFloat64(x)
|
||||
case UntypedInt, UntypedFloat, UntypedComplex:
|
||||
return true
|
||||
}
|
||||
|
||||
case exact.Float:
|
||||
switch as {
|
||||
case Float32:
|
||||
return true // TODO(gri) fix this
|
||||
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 Float32, Complex64:
|
||||
return fitsFloat32(x)
|
||||
case Float64, Complex128:
|
||||
return fitsFloat64(x)
|
||||
case UntypedFloat, UntypedComplex:
|
||||
return true
|
||||
}
|
||||
@ -245,9 +244,9 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
|
||||
case exact.Complex:
|
||||
switch as {
|
||||
case Complex64:
|
||||
return true // TODO(gri) fix this
|
||||
return fitsFloat32(exact.Real(x)) && fitsFloat32(exact.Imag(x))
|
||||
case Complex128:
|
||||
return true // TODO(gri) fix this
|
||||
return fitsFloat64(exact.Real(x)) && fitsFloat64(exact.Imag(x))
|
||||
case UntypedComplex:
|
||||
return true
|
||||
}
|
||||
@ -540,9 +539,9 @@ func (check *checker) shift(x, y *operand, op token.Token) {
|
||||
if x.mode == constant {
|
||||
if y.mode == constant {
|
||||
// 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)
|
||||
if !ok || s >= stupidShift {
|
||||
if !ok || s > stupidShift {
|
||||
check.invalidOp(y.pos(), "%s: stupid shift", y)
|
||||
x.mode = invalid
|
||||
return
|
||||
|
157
go/types/testdata/const1.src
vendored
Normal file
157
go/types/testdata/const1.src
vendored
Normal file
@ -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
|
||||
)
|
2
go/types/testdata/shifts.src
vendored
2
go/types/testdata/shifts.src
vendored
@ -15,7 +15,7 @@ func shifts1() {
|
||||
v2 = 1<<u0
|
||||
v3 = 1<<"foo" /* ERROR "cannot convert" */
|
||||
v4 = 1<<- /* ERROR "stupid shift" */ 1
|
||||
v5 = 1<<1025 /* ERROR "stupid shift" */
|
||||
v5 = 1<<1075 /* ERROR "stupid shift" */
|
||||
v6 = 1 /* ERROR "overflows" */ <<100
|
||||
|
||||
v10 uint = 1 << 0
|
||||
|
Loading…
Reference in New Issue
Block a user