diff options
author | Matthew Dempsky <mdempsky@google.com> | 2020-03-27 14:33:54 -0700 |
---|---|---|
committer | Dmitri Shuralyov <dmitshur@golang.org> | 2020-05-08 16:33:58 +0000 |
commit | f4274e64aac99aaa9af05988f2f8c36c47554889 (patch) | |
tree | 9d4c78eb3aab8d1f62a61e6500e4fb17c9626e70 | |
parent | b7eca1cf3e27ab0796dd8766bf8cc08b14b3cc0d (diff) | |
download | go-f4274e64aac99aaa9af05988f2f8c36c47554889.tar.gz go-f4274e64aac99aaa9af05988f2f8c36c47554889.zip |
[release-branch.go1.14] 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 #38123.
For #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>
(cherry picked from commit 34314280e46da1558bc7f9cd7e8a9ed610cf417b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/232719
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
-rw-r--r-- | src/cmd/compile/internal/gc/subr.go | 12 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/typecheck.go | 2 | ||||
-rw-r--r-- | test/fixedbugs/issue38117.go | 17 |
3 files changed, 28 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 3b085a0d64..73ed34f86a 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -542,7 +542,7 @@ func methtype(t *types.Type) *types.Type { // Is type src assignment compatible to type dst? // If so, return op code to use in conversion. // If not, return 0. -func assignop(src *types.Type, dst *types.Type, why *string) Op { +func assignop(src, dst *types.Type, why *string) Op { if why != nil { *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? // If so, return op code to use in conversion (maybe OCONVNOP). // If not, return 0. -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 { *why = "" } @@ -741,6 +742,13 @@ func convertop(src *types.Type, dst *types.Type, why *string) Op { 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 // and dst is a string type. if src.IsInteger() && dst.IsString() { diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index ae2e16760d..2ed736367f 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -1634,7 +1634,7 @@ func typecheck1(n *Node, top int) (res *Node) { return n } 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.Diag() && !n.Type.Broke() && !n.Left.Diag() { yyerror("cannot convert %L to type %v%s", n.Left, n.Type, why) diff --git a/test/fixedbugs/issue38117.go b/test/fixedbugs/issue38117.go new file mode 100644 index 0000000000..11edef7f25 --- /dev/null +++ b/test/fixedbugs/issue38117.go @@ -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" +) |