Commit fe77a541 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: fix constant pointer comparison failure

Previously, constant pointer-typed expressions could use either Mpint
or NilVal as their Val depending on their construction, but const.go
expects each type to have a single corresponding Val kind.

This CL changes pointer-typed expressions to exclusively use Mpint.

Fixes #21221.

Change-Id: I6ba36c9b11eb19a68306f0b296acb11a8c254c41
Reviewed-on: https://go-review.googlesource.com/105315
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent c3473c4f
...@@ -319,7 +319,8 @@ func (p *importer) pkg() *types.Pkg { ...@@ -319,7 +319,8 @@ func (p *importer) pkg() *types.Pkg {
} }
func idealType(typ *types.Type) *types.Type { func idealType(typ *types.Type) *types.Type {
if typ.IsUntyped() { switch typ {
case types.Idealint, types.Idealrune, types.Idealfloat, types.Idealcomplex:
// canonicalize ideal types // canonicalize ideal types
typ = types.Types[TIDEAL] typ = types.Types[TIDEAL]
} }
...@@ -795,8 +796,12 @@ func (p *importer) value(typ *types.Type) (x Val) { ...@@ -795,8 +796,12 @@ func (p *importer) value(typ *types.Type) (x Val) {
case floatTag: case floatTag:
f := newMpflt() f := newMpflt()
p.float(f) p.float(f)
if typ == types.Idealint || typ.IsInteger() { if typ == types.Idealint || typ.IsInteger() || typ.IsPtr() || typ.IsUnsafePtr() {
// uncommon case: large int encoded as float // uncommon case: large int encoded as float
//
// This happens for unsigned typed integers
// and (on 64-bit platforms) pointers because
// of values in the range [2^63, 2^64).
u := new(Mpint) u := new(Mpint)
u.SetFloat(f) u.SetFloat(f)
x.U = u x.U = u
...@@ -929,18 +934,7 @@ func (p *importer) node() *Node { ...@@ -929,18 +934,7 @@ func (p *importer) node() *Node {
pos := p.pos() pos := p.pos()
typ := p.typ() typ := p.typ()
n := npos(pos, nodlit(p.value(typ))) n := npos(pos, nodlit(p.value(typ)))
if !typ.IsUntyped() { n.Type = idealType(typ)
// Type-checking simplifies unsafe.Pointer(uintptr(c))
// to unsafe.Pointer(c) which then cannot type-checked
// again. Re-introduce explicit uintptr(c) conversion.
// (issue 16317).
if typ.IsUnsafePtr() {
n = nodl(pos, OCONV, n, nil)
n.Type = types.Types[TUINTPTR]
}
n = nodl(pos, OCONV, n, nil)
n.Type = typ
}
return n return n
case ONAME: case ONAME:
......
...@@ -331,26 +331,11 @@ func convlit1(n *Node, t *types.Type, explicit bool, reuse canReuseNode) *Node { ...@@ -331,26 +331,11 @@ func convlit1(n *Node, t *types.Type, explicit bool, reuse canReuseNode) *Node {
case TARRAY: case TARRAY:
goto bad goto bad
case TPTR32, case TPTR32, TPTR64, TUNSAFEPTR:
TPTR64, n.SetVal(Val{new(Mpint)})
TINTER,
TMAP,
TCHAN,
TFUNC,
TSLICE,
TUNSAFEPTR:
break
// A nil literal may be converted to uintptr case TCHAN, TFUNC, TINTER, TMAP, TSLICE:
// if it is an unsafe.Pointer break
case TUINTPTR:
if n.Type.Etype == TUNSAFEPTR {
i := new(Mpint)
i.SetInt64(0)
n.SetVal(Val{i})
} else {
goto bad
}
} }
case CTSTR, CTBOOL: case CTSTR, CTBOOL:
......
...@@ -145,7 +145,7 @@ func importconst(pos src.XPos, pkg *types.Pkg, s *types.Sym, t *types.Type, val ...@@ -145,7 +145,7 @@ func importconst(pos src.XPos, pkg *types.Pkg, s *types.Sym, t *types.Type, val
} }
n := npos(pos, nodlit(val)) n := npos(pos, nodlit(val))
n = convlit1(n, t, false, reuseOK) n.Type = t
n.Sym = s n.Sym = s
declare(n, PEXTERN) declare(n, PEXTERN)
......
...@@ -90,5 +90,5 @@ func main() { ...@@ -90,5 +90,5 @@ func main() {
const ptr = nil // ERROR "const.*nil" const ptr = nil // ERROR "const.*nil"
const _ = string([]byte(nil)) // ERROR "is not a? ?constant" const _ = string([]byte(nil)) // ERROR "is not a? ?constant"
const _ = uintptr(unsafe.Pointer((*int)(nil))) // ERROR "is not a? ?constant" const _ = uintptr(unsafe.Pointer((*int)(nil))) // ERROR "is not a? ?constant"
const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil|invalid constant type" const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil|invalid constant type|is not a constant"
const _ = (*int)(nil) // ERROR "cannot be nil|invalid constant type" const _ = (*int)(nil) // ERROR "cannot be nil|invalid constant type|is not a constant"
// run
// 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.
package main
import "unsafe"
func main() {
if unsafe.Pointer(uintptr(0)) != unsafe.Pointer(nil) {
panic("fail")
}
if (*int)(unsafe.Pointer(uintptr(0))) != (*int)(nil) {
panic("fail")
}
}
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