Skip to content

Commit eb6c433

Browse files
committed
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 <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 3f9efe7 commit eb6c433

File tree

7 files changed

+91
-5
lines changed

7 files changed

+91
-5
lines changed

src/cmd/compile/internal/gc/const.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,7 @@ func (n *Node) isGoConst() bool {
13271327
}
13281328
return true
13291329

1330-
case OCONV:
1330+
case OCONV, OCONVNOP:
13311331
if okforconst[n.Type.Etype] && n.Left.isGoConst() {
13321332
return true
13331333
}

src/cmd/compile/internal/gc/swt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ func checkDupExprCases(exprname *Node, clauses []*Node) {
679679
seen := make(map[typeVal]*Node)
680680
for _, ncase := range clauses {
681681
for _, n := range ncase.List.Slice() {
682-
if ct := consttype(n); ct == 0 || ct == CTBOOL {
682+
if ct := consttype(n); ct == 0 || ct == CTBOOL || ct == CTNIL {
683683
continue
684684
}
685685
tv := typeVal{

src/cmd/compile/internal/gc/typecheck.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,9 +1818,9 @@ func typecheck1(n *Node, top int) (res *Node) {
18181818

18191819
switch n.Op {
18201820
case OCONVNOP:
1821-
if n.Left.Op == OLITERAL {
1822-
n.Op = OCONV
1823-
setconst(n, n.Left.Val())
1821+
if n.Left.Op == OLITERAL && n.isGoConst() {
1822+
n.Op = OCONV // set so n.Orig gets OCONV instead of OCONVNOP
1823+
setconst(n, n.Left.Val()) // convert n to OLITERAL with the given value
18241824
} else if t.Etype == n.Type.Etype {
18251825
switch t.Etype {
18261826
case TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128:

test/fixedbugs/issue28078.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// compile
2+
3+
// Copyright 2018 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Non-constant duplicate keys/cases should not be reported
8+
// as errors by the compiler.
9+
10+
package p
11+
12+
import "unsafe"
13+
14+
func f() {
15+
_ = map[uintptr]int{
16+
0: 0,
17+
uintptr(unsafe.Pointer(nil)): 0,
18+
}
19+
20+
switch uintptr(0) {
21+
case 0:
22+
case uintptr(unsafe.Pointer(nil)):
23+
}
24+
25+
switch interface{}(nil) {
26+
case nil:
27+
case nil:
28+
}
29+
30+
_ = map[interface{}]int{
31+
nil: 0,
32+
nil: 0,
33+
}
34+
}

test/fixedbugs/issue28079a.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// compile
2+
3+
// Copyright 2018 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Non-Go-constant but constant indexes are ok at compile time.
8+
9+
package p
10+
11+
import "unsafe"
12+
13+
func f() {
14+
var x [0]int
15+
x[uintptr(unsafe.Pointer(nil))] = 0
16+
}
17+
func g() {
18+
var x [10]int
19+
_ = x[3:uintptr(unsafe.Pointer(nil))]
20+
}

test/fixedbugs/issue28079b.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// errorcheck
2+
3+
// Copyright 2018 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Non-Go-constant but constant values aren't ok for array sizes.
8+
9+
package p
10+
11+
import "unsafe"
12+
13+
type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound"
14+
15+
func f() {
16+
_ = complex(1<<uintptr(unsafe.Pointer(nil)), 0)
17+
}

test/fixedbugs/issue28079c.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// errorcheck
2+
3+
// Copyright 2018 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Non-Go-constant but constant values aren't ok for shifts.
8+
9+
package p
10+
11+
import "unsafe"
12+
13+
func f() {
14+
_ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "invalid operation: .*shift of type float64.*"
15+
}

0 commit comments

Comments
 (0)