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