Commit eb6c433e authored by Keith Randall's avatar Keith Randall Committed by Keith Randall

cmd/compile: don't convert non-Go-constants to OLITERALs

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: 's avatarMatthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 3f9efe75
......@@ -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
}
......
......@@ -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{
......
......@@ -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:
......
// 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,
}
}
// 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))]
}
// 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)
}
// 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.*"
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment