mirror of
https://github.com/golang/go
synced 2024-11-26 01:57:56 -07:00
[dev.regabi] cmd/compile: replace CTNIL with ONIL
Properly speaking, "nil" is a zero value, not a constant. So go/constant does not have a representation for it. To allow replacing Val with constant.Value, we split out ONIL separately from OLITERAL so we can get rid of CTNIL. Passes toolstash-check. Change-Id: I4c8e60cae3b3c91bbac43b3b0cf2a4ade028d6cb Reviewed-on: https://go-review.googlesource.com/c/go/+/272650 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
4af2decf30
commit
88a9e2f9ad
@ -24,7 +24,6 @@ const (
|
||||
CTCPLX
|
||||
CTSTR
|
||||
CTBOOL
|
||||
CTNIL
|
||||
)
|
||||
|
||||
type Val struct {
|
||||
@ -34,7 +33,6 @@ type Val struct {
|
||||
// *Mpflt float when Ctype() == CTFLT
|
||||
// *Mpcplx pair of floats when Ctype() == CTCPLX
|
||||
// string string when Ctype() == CTSTR
|
||||
// *Nilval when Ctype() == CTNIL
|
||||
U interface{}
|
||||
}
|
||||
|
||||
@ -45,8 +43,6 @@ func (v Val) Ctype() Ctype {
|
||||
panic("unreachable")
|
||||
case nil:
|
||||
return CTxxx
|
||||
case *NilVal:
|
||||
return CTNIL
|
||||
case bool:
|
||||
return CTBOOL
|
||||
case *Mpint:
|
||||
@ -71,8 +67,6 @@ func eqval(a, b Val) bool {
|
||||
default:
|
||||
Fatalf("unexpected Ctype for %T", a.U)
|
||||
panic("unreachable")
|
||||
case *NilVal:
|
||||
return true
|
||||
case bool:
|
||||
y := b.U.(bool)
|
||||
return x == y
|
||||
@ -99,8 +93,6 @@ func (v Val) Interface() interface{} {
|
||||
default:
|
||||
Fatalf("unexpected Interface for %T", v.U)
|
||||
panic("unreachable")
|
||||
case *NilVal:
|
||||
return nil
|
||||
case bool, string:
|
||||
return x
|
||||
case *Mpint:
|
||||
@ -112,8 +104,6 @@ func (v Val) Interface() interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
type NilVal struct{}
|
||||
|
||||
// Int64Val returns n as an int64.
|
||||
// n must be an integer or rune constant.
|
||||
func (n *Node) Int64Val() int64 {
|
||||
@ -245,7 +235,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod
|
||||
return n
|
||||
}
|
||||
|
||||
if n.Op == OLITERAL {
|
||||
if n.Op == OLITERAL || n.Op == ONIL {
|
||||
// Can't always set n.Type directly on OLITERAL nodes.
|
||||
// See discussion on CL 20813.
|
||||
n = n.rawcopy()
|
||||
@ -253,6 +243,9 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod
|
||||
|
||||
// Nil is technically not a constant, so handle it specially.
|
||||
if n.Type.Etype == TNIL {
|
||||
if n.Op != ONIL {
|
||||
Fatalf("unexpected op: %v (%v)", n, n.Op)
|
||||
}
|
||||
if t == nil {
|
||||
yyerror("use of untyped nil")
|
||||
n.SetDiag(true)
|
||||
@ -1039,8 +1032,6 @@ func idealType(ct Ctype) *types.Type {
|
||||
return types.UntypedFloat
|
||||
case CTCPLX:
|
||||
return types.UntypedComplex
|
||||
case CTNIL:
|
||||
return types.Types[TNIL]
|
||||
}
|
||||
Fatalf("unexpected Ctype: %v", ct)
|
||||
return nil
|
||||
@ -1189,7 +1180,7 @@ func indexconst(n *Node) int64 {
|
||||
// Expressions derived from nil, like string([]byte(nil)), while they
|
||||
// may be known at compile time, are not Go language constants.
|
||||
func (n *Node) isGoConst() bool {
|
||||
return n.Op == OLITERAL && n.Val().Ctype() != CTNIL
|
||||
return n.Op == OLITERAL
|
||||
}
|
||||
|
||||
func hascallchan(n *Node) bool {
|
||||
|
@ -152,7 +152,7 @@ func mayAffectMemory(n *Node) bool {
|
||||
// We're ignoring things like division by zero, index out of range,
|
||||
// and nil pointer dereference here.
|
||||
switch n.Op {
|
||||
case ONAME, OCLOSUREVAR, OLITERAL:
|
||||
case ONAME, OCLOSUREVAR, OLITERAL, ONIL:
|
||||
return false
|
||||
|
||||
// Left+Right group.
|
||||
|
@ -476,7 +476,7 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) {
|
||||
default:
|
||||
Fatalf("unexpected expr: %v", n)
|
||||
|
||||
case OLITERAL, OGETG, OCLOSUREVAR, OTYPE:
|
||||
case OLITERAL, ONIL, OGETG, OCLOSUREVAR, OTYPE:
|
||||
// nop
|
||||
|
||||
case ONAME:
|
||||
|
@ -571,9 +571,6 @@ func (v Val) vconv(s fmt.State, flag FmtFlag) {
|
||||
case bool:
|
||||
fmt.Fprint(s, u)
|
||||
|
||||
case *NilVal:
|
||||
fmt.Fprint(s, "nil")
|
||||
|
||||
default:
|
||||
fmt.Fprintf(s, "<ctype=%d>", v.Ctype())
|
||||
}
|
||||
@ -1207,6 +1204,7 @@ var opprec = []int{
|
||||
OMAPLIT: 8,
|
||||
ONAME: 8,
|
||||
ONEW: 8,
|
||||
ONIL: 8,
|
||||
ONONAME: 8,
|
||||
OOFFSETOF: 8,
|
||||
OPACK: 8,
|
||||
@ -1323,6 +1321,9 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
||||
case OPAREN:
|
||||
mode.Fprintf(s, "(%v)", n.Left)
|
||||
|
||||
case ONIL:
|
||||
fmt.Fprint(s, "nil")
|
||||
|
||||
case OLITERAL: // this is a bit of a mess
|
||||
if mode == FErr {
|
||||
if n.Orig != nil && n.Orig != n {
|
||||
@ -1334,10 +1335,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
|
||||
n.Orig.exprfmt(s, prec, mode)
|
||||
return
|
||||
}
|
||||
|
||||
if n.Type != nil && !n.Type.IsUntyped() {
|
||||
// Need parens when type begins with what might
|
||||
// be misinterpreted as a unary operator: * or <-.
|
||||
|
@ -759,8 +759,6 @@ func constTypeOf(typ *types.Type) Ctype {
|
||||
}
|
||||
|
||||
switch typ.Etype {
|
||||
case TCHAN, TFUNC, TMAP, TNIL, TINTER, TPTR, TSLICE, TUNSAFEPTR:
|
||||
return CTNIL
|
||||
case TBOOL:
|
||||
return CTBOOL
|
||||
case TSTRING:
|
||||
@ -790,9 +788,6 @@ func (w *exportWriter) value(typ *types.Type, v Val) {
|
||||
// and provides a useful consistency check.
|
||||
|
||||
switch constTypeOf(typ) {
|
||||
case CTNIL:
|
||||
// Only one value; nothing to encode.
|
||||
_ = v.U.(*NilVal)
|
||||
case CTBOOL:
|
||||
w.bool(v.U.(bool))
|
||||
case CTSTR:
|
||||
@ -1207,11 +1202,19 @@ func (w *exportWriter) expr(n *Node) {
|
||||
switch op := n.Op; op {
|
||||
// expressions
|
||||
// (somewhat closely following the structure of exprfmt in fmt.go)
|
||||
case OLITERAL:
|
||||
if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
|
||||
case ONIL:
|
||||
if !n.Type.HasNil() {
|
||||
Fatalf("unexpected type for nil: %v", n.Type)
|
||||
}
|
||||
if n.Orig != nil && n.Orig != n {
|
||||
w.expr(n.Orig)
|
||||
break
|
||||
}
|
||||
w.op(OLITERAL)
|
||||
w.pos(n.Pos)
|
||||
w.typ(n.Type)
|
||||
|
||||
case OLITERAL:
|
||||
w.op(OLITERAL)
|
||||
w.pos(n.Pos)
|
||||
w.value(n.Type, n.Val())
|
||||
|
@ -293,7 +293,8 @@ func (r *importReader) doDecl(n *Node) {
|
||||
importalias(r.p.ipkg, pos, n.Sym, typ)
|
||||
|
||||
case 'C':
|
||||
typ, val := r.value()
|
||||
typ := r.typ()
|
||||
val := r.value(typ)
|
||||
|
||||
importconst(r.p.ipkg, pos, n.Sym, typ, val)
|
||||
|
||||
@ -354,12 +355,8 @@ func (r *importReader) doDecl(n *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importReader) value() (typ *types.Type, v Val) {
|
||||
typ = p.typ()
|
||||
|
||||
func (p *importReader) value(typ *types.Type) (v Val) {
|
||||
switch constTypeOf(typ) {
|
||||
case CTNIL:
|
||||
v.U = &NilVal{}
|
||||
case CTBOOL:
|
||||
v.U = p.bool()
|
||||
case CTSTR:
|
||||
@ -810,11 +807,20 @@ func (r *importReader) node() *Node {
|
||||
// case OPAREN:
|
||||
// unreachable - unpacked by exporter
|
||||
|
||||
// case ONIL:
|
||||
// unreachable - mapped to OLITERAL
|
||||
|
||||
case OLITERAL:
|
||||
pos := r.pos()
|
||||
typ, val := r.value()
|
||||
typ := r.typ()
|
||||
|
||||
n := npos(pos, nodlit(val))
|
||||
var n *Node
|
||||
if typ.HasNil() {
|
||||
n = nodnil()
|
||||
} else {
|
||||
n = nodlit(r.value(typ))
|
||||
}
|
||||
n = npos(pos, n)
|
||||
n.Type = typ
|
||||
return n
|
||||
|
||||
|
@ -459,7 +459,7 @@ func inlcopy(n *Node) *Node {
|
||||
}
|
||||
|
||||
switch n.Op {
|
||||
case ONAME, OTYPE, OLITERAL:
|
||||
case ONAME, OTYPE, OLITERAL, ONIL:
|
||||
return n
|
||||
}
|
||||
|
||||
@ -1322,7 +1322,7 @@ func (subst *inlsubst) node(n *Node) *Node {
|
||||
}
|
||||
return n
|
||||
|
||||
case OLITERAL, OTYPE:
|
||||
case OLITERAL, ONIL, OTYPE:
|
||||
// If n is a named constant or type, we can continue
|
||||
// using it in the inline copy. Otherwise, make a copy
|
||||
// so we can update the line number.
|
||||
|
@ -591,12 +591,15 @@ func litsym(n, c *Node, wid int) {
|
||||
if n.Op != ONAME {
|
||||
Fatalf("litsym n op %v", n.Op)
|
||||
}
|
||||
if c.Op != OLITERAL {
|
||||
Fatalf("litsym c op %v", c.Op)
|
||||
}
|
||||
if n.Sym == nil {
|
||||
Fatalf("litsym nil n sym")
|
||||
}
|
||||
if c.Op == ONIL {
|
||||
return
|
||||
}
|
||||
if c.Op != OLITERAL {
|
||||
Fatalf("litsym c op %v", c.Op)
|
||||
}
|
||||
s := n.Sym.Linksym()
|
||||
switch u := c.Val().U.(type) {
|
||||
case bool:
|
||||
|
@ -119,7 +119,7 @@ func (o *Order) cheapExpr(n *Node) *Node {
|
||||
}
|
||||
|
||||
switch n.Op {
|
||||
case ONAME, OLITERAL:
|
||||
case ONAME, OLITERAL, ONIL:
|
||||
return n
|
||||
case OLEN, OCAP:
|
||||
l := o.cheapExpr(n.Left)
|
||||
@ -143,7 +143,7 @@ func (o *Order) cheapExpr(n *Node) *Node {
|
||||
// The intended use is to apply to x when rewriting x += y into x = x + y.
|
||||
func (o *Order) safeExpr(n *Node) *Node {
|
||||
switch n.Op {
|
||||
case ONAME, OLITERAL:
|
||||
case ONAME, OLITERAL, ONIL:
|
||||
return n
|
||||
|
||||
case ODOT, OLEN, OCAP:
|
||||
@ -202,7 +202,7 @@ func isaddrokay(n *Node) bool {
|
||||
// The result of addrTemp MUST be assigned back to n, e.g.
|
||||
// n.Left = o.addrTemp(n.Left)
|
||||
func (o *Order) addrTemp(n *Node) *Node {
|
||||
if consttype(n) != CTxxx {
|
||||
if n.Op == OLITERAL || n.Op == ONIL {
|
||||
// TODO: expand this to all static composite literal nodes?
|
||||
n = defaultlit(n, nil)
|
||||
dowidth(n.Type)
|
||||
|
@ -104,6 +104,9 @@ func (s *InitSchedule) staticcopy(l *Node, r *Node) bool {
|
||||
s.append(nod(OAS, l, conv(r, l.Type)))
|
||||
return true
|
||||
|
||||
case ONIL:
|
||||
return true
|
||||
|
||||
case OLITERAL:
|
||||
if isZero(r) {
|
||||
return true
|
||||
@ -139,7 +142,7 @@ func (s *InitSchedule) staticcopy(l *Node, r *Node) bool {
|
||||
e := &p.E[i]
|
||||
n.Xoffset = l.Xoffset + e.Xoffset
|
||||
n.Type = e.Expr.Type
|
||||
if e.Expr.Op == OLITERAL {
|
||||
if e.Expr.Op == OLITERAL || e.Expr.Op == ONIL {
|
||||
litsym(n, e.Expr, int(n.Type.Width))
|
||||
continue
|
||||
}
|
||||
@ -171,6 +174,9 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool {
|
||||
case ONAME:
|
||||
return s.staticcopy(l, r)
|
||||
|
||||
case ONIL:
|
||||
return true
|
||||
|
||||
case OLITERAL:
|
||||
if isZero(r) {
|
||||
return true
|
||||
@ -232,7 +238,7 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool {
|
||||
e := &p.E[i]
|
||||
n.Xoffset = l.Xoffset + e.Xoffset
|
||||
n.Type = e.Expr.Type
|
||||
if e.Expr.Op == OLITERAL {
|
||||
if e.Expr.Op == OLITERAL || e.Expr.Op == ONIL {
|
||||
litsym(n, e.Expr, int(n.Type.Width))
|
||||
continue
|
||||
}
|
||||
@ -269,13 +275,14 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool {
|
||||
for val.Op == OCONVIFACE {
|
||||
val = val.Left
|
||||
}
|
||||
|
||||
if val.Type.IsInterface() {
|
||||
// val is an interface type.
|
||||
// If val is nil, we can statically initialize l;
|
||||
// both words are zero and so there no work to do, so report success.
|
||||
// If val is non-nil, we have no concrete type to record,
|
||||
// and we won't be able to statically initialize its value, so report failure.
|
||||
return Isconst(val, CTNIL)
|
||||
return val.Op == ONIL
|
||||
}
|
||||
|
||||
markTypeUsedInInterface(val.Type, l.Sym.Linksym())
|
||||
@ -296,7 +303,7 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool {
|
||||
|
||||
// Emit data.
|
||||
if isdirectiface(val.Type) {
|
||||
if Isconst(val, CTNIL) {
|
||||
if val.Op == ONIL {
|
||||
// Nil is zero, nothing to do.
|
||||
return true
|
||||
}
|
||||
@ -462,7 +469,7 @@ func isStaticCompositeLiteral(n *Node) bool {
|
||||
}
|
||||
}
|
||||
return true
|
||||
case OLITERAL:
|
||||
case OLITERAL, ONIL:
|
||||
return true
|
||||
case OCONVIFACE:
|
||||
// See staticassign's OCONVIFACE case for comments.
|
||||
@ -471,9 +478,9 @@ func isStaticCompositeLiteral(n *Node) bool {
|
||||
val = val.Left
|
||||
}
|
||||
if val.Type.IsInterface() {
|
||||
return Isconst(val, CTNIL)
|
||||
return val.Op == ONIL
|
||||
}
|
||||
if isdirectiface(val.Type) && Isconst(val, CTNIL) {
|
||||
if isdirectiface(val.Type) && val.Op == ONIL {
|
||||
return true
|
||||
}
|
||||
return isStaticCompositeLiteral(val)
|
||||
@ -1105,13 +1112,14 @@ func (s *InitSchedule) addvalue(p *InitPlan, xoffset int64, n *Node) {
|
||||
|
||||
func isZero(n *Node) bool {
|
||||
switch n.Op {
|
||||
case ONIL:
|
||||
return true
|
||||
|
||||
case OLITERAL:
|
||||
switch u := n.Val().U.(type) {
|
||||
default:
|
||||
Dump("unexpected literal", n)
|
||||
Fatalf("isZero")
|
||||
case *NilVal:
|
||||
return true
|
||||
case string:
|
||||
return u == ""
|
||||
case bool:
|
||||
|
@ -1993,7 +1993,7 @@ func (s *state) ssaShiftOp(op Op, t *types.Type, u *types.Type) ssa.Op {
|
||||
|
||||
// expr converts the expression n to ssa, adds it to s and returns the ssa result.
|
||||
func (s *state) expr(n *Node) *ssa.Value {
|
||||
if !(n.Op == ONAME || n.Op == OLITERAL && n.Sym != nil) {
|
||||
if hasUniquePos(n) {
|
||||
// ONAMEs and named OLITERALs have the line number
|
||||
// of the decl, not the use. See issue 14742.
|
||||
s.pushLine(n.Pos)
|
||||
@ -2029,6 +2029,16 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||
case OCLOSUREVAR:
|
||||
addr := s.addr(n)
|
||||
return s.load(n.Type, addr)
|
||||
case ONIL:
|
||||
t := n.Type
|
||||
switch {
|
||||
case t.IsSlice():
|
||||
return s.constSlice(t)
|
||||
case t.IsInterface():
|
||||
return s.constInterface(t)
|
||||
default:
|
||||
return s.constNil(t)
|
||||
}
|
||||
case OLITERAL:
|
||||
switch u := n.Val().U.(type) {
|
||||
case *Mpint:
|
||||
@ -2053,16 +2063,6 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||
return s.entryNewValue0A(ssa.OpConstString, n.Type, u)
|
||||
case bool:
|
||||
return s.constBool(u)
|
||||
case *NilVal:
|
||||
t := n.Type
|
||||
switch {
|
||||
case t.IsSlice():
|
||||
return s.constSlice(t)
|
||||
case t.IsInterface():
|
||||
return s.constInterface(t)
|
||||
default:
|
||||
return s.constNil(t)
|
||||
}
|
||||
case *Mpflt:
|
||||
switch n.Type.Size() {
|
||||
case 4:
|
||||
|
@ -41,7 +41,7 @@ func hasUniquePos(n *Node) bool {
|
||||
switch n.Op {
|
||||
case ONAME, OPACK:
|
||||
return false
|
||||
case OLITERAL, OTYPE:
|
||||
case OLITERAL, ONIL, OTYPE:
|
||||
if n.Sym != nil {
|
||||
return false
|
||||
}
|
||||
@ -257,7 +257,9 @@ func nodintconst(v int64) *Node {
|
||||
}
|
||||
|
||||
func nodnil() *Node {
|
||||
return nodlit(Val{new(NilVal)})
|
||||
n := nod(ONIL, nil, nil)
|
||||
n.Type = types.Types[TNIL]
|
||||
return n
|
||||
}
|
||||
|
||||
func nodbool(b bool) *Node {
|
||||
@ -298,7 +300,7 @@ func treecopy(n *Node, pos src.XPos) *Node {
|
||||
// crashing (golang.org/issue/11361).
|
||||
fallthrough
|
||||
|
||||
case ONAME, ONONAME, OLITERAL, OTYPE:
|
||||
case ONAME, ONONAME, OLITERAL, ONIL, OTYPE:
|
||||
return n
|
||||
|
||||
}
|
||||
@ -308,7 +310,7 @@ func treecopy(n *Node, pos src.XPos) *Node {
|
||||
func (n *Node) isNil() bool {
|
||||
// Check n.Orig because constant propagation may produce typed nil constants,
|
||||
// which don't exist in the Go spec.
|
||||
return Isconst(n.Orig, CTNIL)
|
||||
return n.Orig.Op == ONIL
|
||||
}
|
||||
|
||||
func isptrto(t *types.Type, et types.EType) bool {
|
||||
@ -807,7 +809,7 @@ func calcHasCall(n *Node) bool {
|
||||
}
|
||||
|
||||
switch n.Op {
|
||||
case OLITERAL, ONAME, OTYPE:
|
||||
case OLITERAL, ONIL, ONAME, OTYPE:
|
||||
if n.HasCall() {
|
||||
Fatalf("OLITERAL/ONAME/OTYPE should never have calls: %+v", n)
|
||||
}
|
||||
@ -926,7 +928,7 @@ func safeexpr(n *Node, init *Nodes) *Node {
|
||||
}
|
||||
|
||||
switch n.Op {
|
||||
case ONAME, OLITERAL:
|
||||
case ONAME, OLITERAL, ONIL:
|
||||
return n
|
||||
|
||||
case ODOT, OLEN, OCAP:
|
||||
@ -988,7 +990,7 @@ func copyexpr(n *Node, t *types.Type, init *Nodes) *Node {
|
||||
// result may not be assignable.
|
||||
func cheapexpr(n *Node, init *Nodes) *Node {
|
||||
switch n.Op {
|
||||
case ONAME, OLITERAL:
|
||||
case ONAME, OLITERAL, ONIL:
|
||||
return n
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ func walkExprSwitch(sw *Node) {
|
||||
}
|
||||
|
||||
cond = walkexpr(cond, &sw.Ninit)
|
||||
if cond.Op != OLITERAL {
|
||||
if cond.Op != OLITERAL && cond.Op != ONIL {
|
||||
cond = copyexpr(cond, cond.Type, &sw.Nbody)
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,7 @@ func (n *Node) SetIota(x int64) {
|
||||
// Extra care must be taken when mutating such a node.
|
||||
func (n *Node) mayBeShared() bool {
|
||||
switch n.Op {
|
||||
case ONAME, OLITERAL, OTYPE:
|
||||
case ONAME, OLITERAL, ONIL, OTYPE:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -363,7 +363,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
n.Type = types.UntypedString
|
||||
}
|
||||
|
||||
case ONONAME:
|
||||
case ONIL, ONONAME:
|
||||
ok |= ctxExpr
|
||||
|
||||
case ONAME:
|
||||
@ -1590,7 +1590,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
|
||||
n.Type = t
|
||||
if !t.IsSlice() {
|
||||
if Isconst(args.First(), CTNIL) {
|
||||
if args.First().isNil() {
|
||||
yyerror("first argument to append must be typed slice; have untyped nil")
|
||||
n.Type = nil
|
||||
return n
|
||||
@ -3193,6 +3193,9 @@ func samesafeexpr(l *Node, r *Node) bool {
|
||||
|
||||
case OLITERAL:
|
||||
return eqval(l.Val(), r.Val())
|
||||
|
||||
case ONIL:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
@ -3596,7 +3599,7 @@ func typecheckdef(n *Node) {
|
||||
}
|
||||
if !e.isGoConst() {
|
||||
if !e.Diag() {
|
||||
if Isconst(e, CTNIL) {
|
||||
if e.Op == ONIL {
|
||||
yyerrorl(n.Pos, "const initializer cannot be nil")
|
||||
} else {
|
||||
yyerrorl(n.Pos, "const initializer %v is not a constant", e)
|
||||
|
@ -157,9 +157,7 @@ func lexinit() {
|
||||
|
||||
types.Types[TNIL] = types.New(TNIL)
|
||||
s = builtinpkg.Lookup("nil")
|
||||
var v Val
|
||||
v.U = new(NilVal)
|
||||
s.Def = asTypesNode(nodlit(v))
|
||||
s.Def = asTypesNode(nodnil())
|
||||
asNode(s.Def).Sym = s
|
||||
asNode(s.Def).Name = new(Name)
|
||||
|
||||
|
@ -465,7 +465,7 @@ opswitch:
|
||||
|
||||
case ONONAME, OEMPTY, OGETG, ONEWOBJ:
|
||||
|
||||
case OTYPE, ONAME, OLITERAL:
|
||||
case OTYPE, ONAME, OLITERAL, ONIL:
|
||||
// TODO(mdempsky): Just return n; see discussion on CL 38655.
|
||||
// Perhaps refactor to use Node.mayBeShared for these instead.
|
||||
// If these return early, make sure to still call
|
||||
@ -2277,7 +2277,7 @@ func varexpr(n *Node) bool {
|
||||
}
|
||||
|
||||
switch n.Op {
|
||||
case OLITERAL:
|
||||
case OLITERAL, ONIL:
|
||||
return true
|
||||
|
||||
case ONAME:
|
||||
@ -2332,7 +2332,7 @@ func vmatch2(l *Node, r *Node) bool {
|
||||
case ONAME:
|
||||
return l == r
|
||||
|
||||
case OLITERAL:
|
||||
case OLITERAL, ONIL:
|
||||
return false
|
||||
}
|
||||
|
||||
@ -2373,7 +2373,7 @@ func vmatch1(l *Node, r *Node) bool {
|
||||
|
||||
return vmatch2(l, r)
|
||||
|
||||
case OLITERAL:
|
||||
case OLITERAL, ONIL:
|
||||
return false
|
||||
}
|
||||
|
||||
@ -3190,7 +3190,7 @@ func eqfor(t *types.Type) (n *Node, needsize bool) {
|
||||
// The result of walkcompare MUST be assigned back to n, e.g.
|
||||
// n.Left = walkcompare(n.Left, init)
|
||||
func walkcompare(n *Node, init *Nodes) *Node {
|
||||
if n.Left.Type.IsInterface() && n.Right.Type.IsInterface() && n.Left.Op != OLITERAL && n.Right.Op != OLITERAL {
|
||||
if n.Left.Type.IsInterface() && n.Right.Type.IsInterface() && n.Left.Op != ONIL && n.Right.Op != ONIL {
|
||||
return walkcompareInterface(n, init)
|
||||
}
|
||||
|
||||
@ -3788,6 +3788,7 @@ func candiscard(n *Node) bool {
|
||||
OTYPE,
|
||||
OPACK,
|
||||
OLITERAL,
|
||||
ONIL,
|
||||
OADD,
|
||||
OSUB,
|
||||
OOR,
|
||||
|
@ -1265,7 +1265,7 @@ func (t *Type) IsPtrShaped() bool {
|
||||
// HasNil reports whether the set of values determined by t includes nil.
|
||||
func (t *Type) HasNil() bool {
|
||||
switch t.Etype {
|
||||
case TCHAN, TFUNC, TINTER, TMAP, TPTR, TSLICE, TUNSAFEPTR:
|
||||
case TCHAN, TFUNC, TINTER, TMAP, TNIL, TPTR, TSLICE, TUNSAFEPTR:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
Loading…
Reference in New Issue
Block a user