]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: replace CTNIL with ONIL
authorMatthew Dempsky <mdempsky@google.com>
Sat, 14 Nov 2020 04:38:21 +0000 (20:38 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 24 Nov 2020 19:34:23 +0000 (19:34 +0000)
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>

18 files changed:
src/cmd/compile/internal/gc/const.go
src/cmd/compile/internal/gc/esc.go
src/cmd/compile/internal/gc/escape.go
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/iimport.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/obj.go
src/cmd/compile/internal/gc/order.go
src/cmd/compile/internal/gc/sinit.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/swt.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/universe.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/types/type.go

index b92c8d66b5afb1039c2fff5e0e8b73864ac6135b..42ac3a26f8cbb3e4f33c60a2e8862a75b09536f9 100644 (file)
@@ -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 {
index 6f328ab5ea9362da3eb44b0c8670459657c6c5d0..b7d1dfc92a5f561fc66666757a493d73d4395106 100644 (file)
@@ -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.
index 757b4652ca6753b7295ccea6834a1d1e62d8d1a6..bc0eb98d7625af7f161bdd5c244fc352a8da6c50 100644 (file)
@@ -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:
index f61ea8aaac91570b4bfdb8841b75a76ccbd27616..9b57d131b1fa12e37c1d2772b98e6d1cfd549866 100644 (file)
@@ -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 <-.
index 47910eb3b90247986d1fb744271f52708a7373be..b48a840d00000320f86b7c55fceb67a852f6b442 100644 (file)
@@ -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())
index df193cd8e1d86f3b396101ff96a155a7437c4ff0..ac565a6632c9af9f1ffe418a5d7611fe8f7be053 100644 (file)
@@ -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
 
index 4aa561da6e9eb2a2305372024473e1eecedfa381..a882e91dceedb47e5dbb9924efee1ae53701dbf8 100644 (file)
@@ -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.
index 8fe480b65f58757554a4ac1a0ec97139e423ee71..77f9afb44dada107aabe968b4dbb15a8bd8dc326 100644 (file)
@@ -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:
index 863de5b6c71b49ddc32e65e9b4bb29c90e029922..11c8b1fa25e5f942f0a8176fd911af7342728032 100644 (file)
@@ -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)
index 212fcc022dba36dcfe26dc1a3695800eedfec762..c199ff6317d0b4bc23db990b64d9939c2816a1d7 100644 (file)
@@ -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:
index 0b38e70cd2a95562f7bf6f1a6ab1b5356d610fb0..709b2d434ed28a91f24571b6e0bd30be233382ba 100644 (file)
@@ -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:
index 849043bfe22ea3816360fd671573a89a8234dec3..7c13aef21403b6c573e295fc7695bc432677e562 100644 (file)
@@ -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
        }
 
index 9ab5f0c2487e1c9681b043778aaade00c67bac70..5f4e9e4b408d22af9fd7872356e53fe89862f50a 100644 (file)
@@ -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)
        }
 
index b86510a2948047e3bb6ca84735ebf59a6c61fdb0..f364ed1527fc7525f442fdd8065c5b2b44538103 100644 (file)
@@ -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
index f13d9a3e2659be863077e6a0c08628d894fc1a9d..32619b08d1fbe06714b776b0369627c5813ff791 100644 (file)
@@ -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)
index 559d47da1a090a4f1b5c0bebce7bf8995949727a..32bf37e3228cbcc1ca3290327f2e1117170b43a9 100644 (file)
@@ -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)
 
index a61cb3f6517428b1f360d3a03eb3b25ff11a9916..ac43a8e1bea546d254fd9050142f1bc0d3755cc1 100644 (file)
@@ -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,
index 62c5c344845ad27f43d6b7b0446162e245e73ed1..82db9e4dbcba60d0bc0cac1a4dfa37318b243ef8 100644 (file)
@@ -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