1
0
mirror of https://github.com/golang/go synced 2024-11-18 19:34:41 -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:
Robert Griesemer 2013-07-26 18:21:14 -07:00
parent 41fb587948
commit 4ea4ce9e03
4 changed files with 187 additions and 30 deletions

View File

@ -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"},

View File

@ -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
View 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
)

View File

@ -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