mirror of
https://github.com/golang/go
synced 2024-11-22 22:50:03 -07:00
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: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
c3473c4f10
commit
fe77a5413e
@ -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) {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
|||||||
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"
|
||||||
|
18
test/fixedbugs/issue21221.go
Normal file
18
test/fixedbugs/issue21221.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user