]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't convert non-Go-constants to OLITERALs
authorKeith Randall <khr@google.com>
Mon, 26 Nov 2018 23:58:03 +0000 (15:58 -0800)
committerKeith Randall <khr@golang.org>
Tue, 27 Nov 2018 01:21:41 +0000 (01:21 +0000)
Don't convert values that aren't Go constants, like
uintptr(unsafe.Pointer(nil)), to a literal constant. This avoids
assuming they are constants for things like indexing, array sizes,
case duplication, etc.

Also, nil is an allowed duplicate in switches. CTNILs aren't Go constants.

Fixes #28078
Fixes #28079

Change-Id: I9ab8af47098651ea09ef10481787eae2ae2fb445
Reviewed-on: https://go-review.googlesource.com/c/151320
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/const.go
src/cmd/compile/internal/gc/swt.go
src/cmd/compile/internal/gc/typecheck.go
test/fixedbugs/issue28078.go [new file with mode: 0644]
test/fixedbugs/issue28079a.go [new file with mode: 0644]
test/fixedbugs/issue28079b.go [new file with mode: 0644]
test/fixedbugs/issue28079c.go [new file with mode: 0644]

index afcdb95443a0b15cdd28675f349435681590935a..c01820506deb63729c628a2c185a79c803803ba1 100644 (file)
@@ -1327,7 +1327,7 @@ func (n *Node) isGoConst() bool {
                }
                return true
 
-       case OCONV:
+       case OCONV, OCONVNOP:
                if okforconst[n.Type.Etype] && n.Left.isGoConst() {
                        return true
                }
index b475e7adc3d57e32b798920a3c6528e962684896..a985626a02e265614ba0d433a50e5cc67190a42b 100644 (file)
@@ -679,7 +679,7 @@ func checkDupExprCases(exprname *Node, clauses []*Node) {
        seen := make(map[typeVal]*Node)
        for _, ncase := range clauses {
                for _, n := range ncase.List.Slice() {
-                       if ct := consttype(n); ct == 0 || ct == CTBOOL {
+                       if ct := consttype(n); ct == 0 || ct == CTBOOL || ct == CTNIL {
                                continue
                        }
                        tv := typeVal{
index 069a38cbbbe19dbb1226535c482ed4f8f05dff15..cbca68541577e878cd7ea0a4c6fb1e5021e3e3d8 100644 (file)
@@ -1818,9 +1818,9 @@ func typecheck1(n *Node, top int) (res *Node) {
 
                switch n.Op {
                case OCONVNOP:
-                       if n.Left.Op == OLITERAL {
-                               n.Op = OCONV
-                               setconst(n, n.Left.Val())
+                       if n.Left.Op == OLITERAL && n.isGoConst() {
+                               n.Op = OCONV              // set so n.Orig gets OCONV instead of OCONVNOP
+                               setconst(n, n.Left.Val()) // convert n to OLITERAL with the given value
                        } else if t.Etype == n.Type.Etype {
                                switch t.Etype {
                                case TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128:
diff --git a/test/fixedbugs/issue28078.go b/test/fixedbugs/issue28078.go
new file mode 100644 (file)
index 0000000..2e4c4b5
--- /dev/null
@@ -0,0 +1,34 @@
+// compile
+
+// Copyright 2018 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.
+
+// Non-constant duplicate keys/cases should not be reported
+// as errors by the compiler.
+
+package p
+
+import "unsafe"
+
+func f() {
+       _ = map[uintptr]int{
+               0:                            0,
+               uintptr(unsafe.Pointer(nil)): 0,
+       }
+
+       switch uintptr(0) {
+       case 0:
+       case uintptr(unsafe.Pointer(nil)):
+       }
+
+       switch interface{}(nil) {
+       case nil:
+       case nil:
+       }
+
+       _ = map[interface{}]int{
+               nil: 0,
+               nil: 0,
+       }
+}
diff --git a/test/fixedbugs/issue28079a.go b/test/fixedbugs/issue28079a.go
new file mode 100644 (file)
index 0000000..b0631bb
--- /dev/null
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2018 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.
+
+// Non-Go-constant but constant indexes are ok at compile time.
+
+package p
+
+import "unsafe"
+
+func f() {
+       var x [0]int
+       x[uintptr(unsafe.Pointer(nil))] = 0
+}
+func g() {
+       var x [10]int
+       _ = x[3:uintptr(unsafe.Pointer(nil))]
+}
diff --git a/test/fixedbugs/issue28079b.go b/test/fixedbugs/issue28079b.go
new file mode 100644 (file)
index 0000000..47cc16d
--- /dev/null
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2018 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.
+
+// Non-Go-constant but constant values aren't ok for array sizes.
+
+package p
+
+import "unsafe"
+
+type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound"
+
+func f() {
+       _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0)
+}
diff --git a/test/fixedbugs/issue28079c.go b/test/fixedbugs/issue28079c.go
new file mode 100644 (file)
index 0000000..bea1898
--- /dev/null
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2018 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.
+
+// Non-Go-constant but constant values aren't ok for shifts.
+
+package p
+
+import "unsafe"
+
+func f() {
+       _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "invalid operation: .*shift of type float64.*"
+}