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: 's avatarRobert Griesemer <gri@golang.org>
parent c3473c4f
......@@ -319,7 +319,8 @@ func (p *importer) pkg() *types.Pkg {
}
func idealType(typ *types.Type) *types.Type {
if typ.IsUntyped() {
switch typ {
case types.Idealint, types.Idealrune, types.Idealfloat, types.Idealcomplex:
// canonicalize ideal types
typ = types.Types[TIDEAL]
}
......@@ -795,8 +796,12 @@ func (p *importer) value(typ *types.Type) (x Val) {
case floatTag:
f := newMpflt()
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
//
// 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.SetFloat(f)
x.U = u
......@@ -929,18 +934,7 @@ func (p *importer) node() *Node {
pos := p.pos()
typ := p.typ()
n := npos(pos, nodlit(p.value(typ)))
if !typ.IsUntyped() {
// 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
}
n.Type = idealType(typ)
return n
case ONAME:
......
......@@ -331,26 +331,11 @@ func convlit1(n *Node, t *types.Type, explicit bool, reuse canReuseNode) *Node {
case TARRAY:
goto bad
case TPTR32,
TPTR64,
TINTER,
TMAP,
TCHAN,
TFUNC,
TSLICE,
TUNSAFEPTR:
break
case TPTR32, TPTR64, TUNSAFEPTR:
n.SetVal(Val{new(Mpint)})
// A nil literal may be converted to uintptr
// if it is an unsafe.Pointer
case TUINTPTR:
if n.Type.Etype == TUNSAFEPTR {
i := new(Mpint)
i.SetInt64(0)
n.SetVal(Val{i})
} else {
goto bad
}
case TCHAN, TFUNC, TINTER, TMAP, TSLICE:
break
}
case CTSTR, CTBOOL:
......
......@@ -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 = convlit1(n, t, false, reuseOK)
n.Type = t
n.Sym = s
declare(n, PEXTERN)
......
......@@ -90,5 +90,5 @@ func main() {
const ptr = nil // ERROR "const.*nil"
const _ = string([]byte(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 _ = (*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|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