mirror of
https://github.com/golang/go
synced 2024-11-26 14:36:52 -07:00
cmd/compile: fix constant conversion involving complex types
In CL 187657, I refactored constant conversion logic without realizing that conversions between int/float and complex types are allowed for constants (assuming the constant values are representable by the destination type), but are never allowed for non-constant expressions. This CL expands convertop to take an extra srcConstant parameter to indicate whether the source expression is a constant; and if so, to allow any numeric-to-numeric conversion. (Conversions of values that cannot be represented in the destination type are rejected by evconst.) Fixes #38117. Change-Id: Id7077d749a14c8fd910be38da170fa5254819f2b Reviewed-on: https://go-review.googlesource.com/c/go/+/226197 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
faa53e17d1
commit
34314280e4
@ -542,7 +542,7 @@ func methtype(t *types.Type) *types.Type {
|
|||||||
// Is type src assignment compatible to type dst?
|
// Is type src assignment compatible to type dst?
|
||||||
// If so, return op code to use in conversion.
|
// If so, return op code to use in conversion.
|
||||||
// If not, return OXXX.
|
// If not, return OXXX.
|
||||||
func assignop(src *types.Type, dst *types.Type, why *string) Op {
|
func assignop(src, dst *types.Type, why *string) Op {
|
||||||
if why != nil {
|
if why != nil {
|
||||||
*why = ""
|
*why = ""
|
||||||
}
|
}
|
||||||
@ -665,7 +665,8 @@ func assignop(src *types.Type, dst *types.Type, why *string) Op {
|
|||||||
// Can we convert a value of type src to a value of type dst?
|
// Can we convert a value of type src to a value of type dst?
|
||||||
// If so, return op code to use in conversion (maybe OCONVNOP).
|
// If so, return op code to use in conversion (maybe OCONVNOP).
|
||||||
// If not, return OXXX.
|
// If not, return OXXX.
|
||||||
func convertop(src *types.Type, dst *types.Type, why *string) Op {
|
// srcConstant indicates whether the value of type src is a constant.
|
||||||
|
func convertop(srcConstant bool, src, dst *types.Type, why *string) Op {
|
||||||
if why != nil {
|
if why != nil {
|
||||||
*why = ""
|
*why = ""
|
||||||
}
|
}
|
||||||
@ -741,6 +742,13 @@ func convertop(src *types.Type, dst *types.Type, why *string) Op {
|
|||||||
return OCONV
|
return OCONV
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case for constant conversions: any numeric
|
||||||
|
// conversion is potentially okay. We'll validate further
|
||||||
|
// within evconst. See #38117.
|
||||||
|
if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
|
||||||
|
return OCONV
|
||||||
|
}
|
||||||
|
|
||||||
// 6. src is an integer or has type []byte or []rune
|
// 6. src is an integer or has type []byte or []rune
|
||||||
// and dst is a string type.
|
// and dst is a string type.
|
||||||
if src.IsInteger() && dst.IsString() {
|
if src.IsInteger() && dst.IsString() {
|
||||||
|
@ -1634,7 +1634,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
var why string
|
var why string
|
||||||
n.Op = convertop(t, n.Type, &why)
|
n.Op = convertop(n.Left.Op == OLITERAL, t, n.Type, &why)
|
||||||
if n.Op == 0 {
|
if n.Op == 0 {
|
||||||
if !n.Diag() && !n.Type.Broke() && !n.Left.Diag() {
|
if !n.Diag() && !n.Type.Broke() && !n.Left.Diag() {
|
||||||
yyerror("cannot convert %L to type %v%s", n.Left, n.Type, why)
|
yyerror("cannot convert %L to type %v%s", n.Left, n.Type, why)
|
||||||
|
17
test/fixedbugs/issue38117.go
Normal file
17
test/fixedbugs/issue38117.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// errorcheck
|
||||||
|
|
||||||
|
// Copyright 2020 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.
|
||||||
|
|
||||||
|
// cmd/compile erroneously rejected conversions of constant values
|
||||||
|
// between int/float and complex types.
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ = int(complex64(int(0)))
|
||||||
|
_ = float64(complex128(float64(0)))
|
||||||
|
|
||||||
|
_ = int8(complex128(1000)) // ERROR "overflow"
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user