]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix constant conversion involving complex types
authorMatthew Dempsky <mdempsky@google.com>
Fri, 27 Mar 2020 21:33:54 +0000 (14:33 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 31 Mar 2020 20:59:14 +0000 (20:59 +0000)
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>
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/typecheck.go
test/fixedbugs/issue38117.go [new file with mode: 0644]

index 0a2a11663e08d7b6e281687bb974b6418e45eb90..7c1ab89b78d668f8346a51d2444b881f7274264b 100644 (file)
@@ -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 OXXX.
-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 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 {
                *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() {
index 2ca7f2dbe436ce79ee4fa3539a9c1e990361501e..6e04908b46471b4d4fad5c88942bdd13c63913e0 100644 (file)
@@ -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 (file)
index 0000000..11edef7
--- /dev/null
@@ -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"
+)