cmd/internal/gc: manual goto removal + grind to move var decls
Also change gc.Naddr to return the Addr instead of filling it in.
Change-Id: I98a86705d23bee49626a12a042a4d51cabe290ea
Reviewed-on: https://go-review.googlesource.com/6601
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/src/cmd/5g/ggen.go b/src/cmd/5g/ggen.go
index 374d5e3..58b0c36 100644
--- a/src/cmd/5g/ggen.go
+++ b/src/cmd/5g/ggen.go
@@ -78,7 +78,7 @@
p.Reg = arm.REGSP
p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
f := gc.Sysfunc("duffzero")
- gc.Naddr(f, &p.To, 1)
+ p.To = gc.Naddr(f, 1)
gc.Afunclit(&p.To, f)
p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr))
} else {
diff --git a/src/cmd/5g/gsubr.go b/src/cmd/5g/gsubr.go
index b8547dd..f2ba6e2 100644
--- a/src/cmd/5g/gsubr.go
+++ b/src/cmd/5g/gsubr.go
@@ -766,12 +766,14 @@
// removed.
// requires register destination
rdst:
- regalloc(&r1, t.Type, t)
+ {
+ regalloc(&r1, t.Type, t)
- gins(a, f, &r1)
- gmove(&r1, t)
- regfree(&r1)
- return
+ gins(a, f, &r1)
+ gmove(&r1, t)
+ regfree(&r1)
+ return
+ }
// requires register intermediate
hard:
@@ -844,10 +846,10 @@
var at obj.Addr
if f != nil {
- gc.Naddr(f, &af, 1)
+ af = gc.Naddr(f, 1)
}
if t != nil {
- gc.Naddr(t, &at, 1)
+ at = gc.Naddr(t, 1)
}
p := gc.Prog(as)
if f != nil {
@@ -868,7 +870,7 @@
func raddr(n *gc.Node, p *obj.Prog) {
var a obj.Addr
- gc.Naddr(n, &a, 1)
+ a = gc.Naddr(n, 1)
if a.Type != obj.TYPE_REG {
if n != nil {
gc.Fatal("bad in raddr: %v", gc.Oconv(int(n.Op), 0))
@@ -1304,7 +1306,7 @@
reg1 := &clean[cleani-2]
reg.Op = gc.OEMPTY
reg1.Op = gc.OEMPTY
- gc.Naddr(n, a, 1)
+ *a = gc.Naddr(n, 1)
return true
case gc.ODOT,
@@ -1328,7 +1330,7 @@
n1.Type = n.Type
n1.Xoffset += oary[0]
- gc.Naddr(&n1, a, 1)
+ *a = gc.Naddr(&n1, 1)
return true
}
@@ -1356,7 +1358,7 @@
a.Type = obj.TYPE_NONE
a.Name = obj.NAME_NONE
n1.Type = n.Type
- gc.Naddr(&n1, a, 1)
+ *a = gc.Naddr(&n1, 1)
return true
case gc.OINDEX:
diff --git a/src/cmd/6g/cgen.go b/src/cmd/6g/cgen.go
index 8e28215..0b0d6b3 100644
--- a/src/cmd/6g/cgen.go
+++ b/src/cmd/6g/cgen.go
@@ -1115,8 +1115,6 @@
return
}
- var nr *gc.Node
-
for n.Op == gc.OCONVNOP {
n = n.Left
if n.Ninit != nil {
@@ -1125,6 +1123,7 @@
}
var nl *gc.Node
+ var nr *gc.Node
switch n.Op {
default:
goto def
diff --git a/src/cmd/6g/ggen.go b/src/cmd/6g/ggen.go
index 2934f1e..45242b3 100644
--- a/src/cmd/6g/ggen.go
+++ b/src/cmd/6g/ggen.go
@@ -503,7 +503,6 @@
gmove(&n31, &n3)
}
- var p2 *obj.Prog
var n4 gc.Node
if gc.Nacl {
// Native Client does not relay the divide-by-zero trap
@@ -520,6 +519,7 @@
gc.Patch(p1, gc.Pc)
}
+ var p2 *obj.Prog
if check != 0 {
gc.Nodconst(&n4, t, -1)
gins(optoas(gc.OCMP, t), &n3, &n4)
diff --git a/src/cmd/6g/gsubr.go b/src/cmd/6g/gsubr.go
index 73afb93..719a1fe 100644
--- a/src/cmd/6g/gsubr.go
+++ b/src/cmd/6g/gsubr.go
@@ -314,7 +314,6 @@
}
// cannot have two memory operands
- var r1 gc.Node
var a int
if gc.Ismem(f) && gc.Ismem(t) {
goto hard
@@ -669,15 +668,19 @@
// requires register destination
rdst:
- regalloc(&r1, t.Type, t)
+ {
+ var r1 gc.Node
+ regalloc(&r1, t.Type, t)
- gins(a, f, &r1)
- gmove(&r1, t)
- regfree(&r1)
- return
+ gins(a, f, &r1)
+ gmove(&r1, t)
+ regfree(&r1)
+ return
+ }
// requires register intermediate
hard:
+ var r1 gc.Node
regalloc(&r1, cvt, t)
gmove(f, &r1)
@@ -744,12 +747,12 @@
}
var af obj.Addr
- var at obj.Addr
if f != nil {
- gc.Naddr(f, &af, 1)
+ af = gc.Naddr(f, 1)
}
+ var at obj.Addr
if t != nil {
- gc.Naddr(t, &at, 1)
+ at = gc.Naddr(t, 1)
}
p := gc.Prog(as)
if f != nil {
@@ -1402,7 +1405,7 @@
reg1 := &clean[cleani-2]
reg.Op = gc.OEMPTY
reg1.Op = gc.OEMPTY
- gc.Naddr(n, a, 1)
+ *a = gc.Naddr(n, 1)
return true
case gc.ODOT,
@@ -1426,7 +1429,7 @@
n1.Type = n.Type
n1.Xoffset += oary[0]
- gc.Naddr(&n1, a, 1)
+ *a = gc.Naddr(&n1, 1)
return true
}
@@ -1454,7 +1457,7 @@
a.Type = obj.TYPE_NONE
a.Index = obj.TYPE_NONE
fixlargeoffset(&n1)
- gc.Naddr(&n1, a, 1)
+ *a = gc.Naddr(&n1, 1)
return true
case gc.OINDEX:
diff --git a/src/cmd/6g/peep.go b/src/cmd/6g/peep.go
index 7eff574..a967bba 100644
--- a/src/cmd/6g/peep.go
+++ b/src/cmd/6g/peep.go
@@ -825,8 +825,7 @@
if p.As == obj.AVARDEF || p.As == obj.AVARKILL {
return 0
}
- var info gc.ProgInfo
- info = proginfo(p)
+ info := proginfo(p)
if (info.Reguse|info.Regset)&RtoB(int(v.Reg)) != 0 {
return 2
diff --git a/src/cmd/8g/gsubr.go b/src/cmd/8g/gsubr.go
index 6931ea8..95ec01a 100644
--- a/src/cmd/8g/gsubr.go
+++ b/src/cmd/8g/gsubr.go
@@ -1148,12 +1148,14 @@
// requires register destination
rdst:
- regalloc(&r1, t.Type, t)
+ {
+ regalloc(&r1, t.Type, t)
- gins(a, f, &r1)
- gmove(&r1, t)
- regfree(&r1)
- return
+ gins(a, f, &r1)
+ gmove(&r1, t)
+ regfree(&r1)
+ return
+ }
// requires register intermediate
hard:
@@ -1845,10 +1847,10 @@
var af obj.Addr
var at obj.Addr
if f != nil {
- gc.Naddr(f, &af, 1)
+ af = gc.Naddr(f, 1)
}
if t != nil {
- gc.Naddr(t, &at, 1)
+ at = gc.Naddr(t, 1)
}
p := gc.Prog(as)
if f != nil {
diff --git a/src/cmd/9g/ggen.go b/src/cmd/9g/ggen.go
index 98357eb..d9bcfb7 100644
--- a/src/cmd/9g/ggen.go
+++ b/src/cmd/9g/ggen.go
@@ -76,7 +76,7 @@
p.Reg = ppc64.REGSP
p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
f := gc.Sysfunc("duffzero")
- gc.Naddr(f, &p.To, 1)
+ p.To = gc.Naddr(f, 1)
gc.Afunclit(&p.To, f)
p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr))
} else {
diff --git a/src/cmd/9g/gsubr.go b/src/cmd/9g/gsubr.go
index 2c51d06..1f1a43e 100644
--- a/src/cmd/9g/gsubr.go
+++ b/src/cmd/9g/gsubr.go
@@ -669,12 +669,14 @@
// requires register destination
rdst:
- regalloc(&r1, t.Type, t)
+ {
+ regalloc(&r1, t.Type, t)
- gins(a, f, &r1)
- gmove(&r1, t)
- regfree(&r1)
- return
+ gins(a, f, &r1)
+ gmove(&r1, t)
+ regfree(&r1)
+ return
+ }
// requires register intermediate
hard:
@@ -698,10 +700,10 @@
at := obj.Addr(obj.Addr{})
if f != nil {
- gc.Naddr(f, &af, 1)
+ af = gc.Naddr(f, 1)
}
if t != nil {
- gc.Naddr(t, &at, 1)
+ at = gc.Naddr(t, 1)
}
p := (*obj.Prog)(gc.Prog(as))
if f != nil {
diff --git a/src/cmd/internal/gc/closure.go b/src/cmd/internal/gc/closure.go
index c9b6981..d6f657f 100644
--- a/src/cmd/internal/gc/closure.go
+++ b/src/cmd/internal/gc/closure.go
@@ -596,7 +596,6 @@
declare(xfunc.Nname, PFUNC)
// Declare and initialize variable holding receiver.
- var body *NodeList
xfunc.Needctxt = true
cv := Nod(OCLOSUREVAR, nil, nil)
@@ -613,6 +612,7 @@
ptr.Used = 1
ptr.Curfn = xfunc
xfunc.Dcl = list(xfunc.Dcl, ptr)
+ var body *NodeList
if Isptr[rcvrtype.Etype] || Isinter(rcvrtype) {
ptr.Ntype = typenod(rcvrtype)
body = list(body, Nod(OAS, ptr, cv))
diff --git a/src/cmd/internal/gc/dcl.go b/src/cmd/internal/gc/dcl.go
index 8ea5d8d..a9454e6 100644
--- a/src/cmd/internal/gc/dcl.go
+++ b/src/cmd/internal/gc/dcl.go
@@ -313,7 +313,6 @@
* new_name_list [[type] = expr_list]
*/
func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
- var vv *NodeList
if cl == nil {
if t != nil {
Yyerror("const declaration cannot have type without expression")
@@ -329,6 +328,7 @@
var v *Node
var c *Node
+ var vv *NodeList
for ; vl != nil; vl = vl.Next {
if cl == nil {
Yyerror("missing value in const declaration")
diff --git a/src/cmd/internal/gc/gsubr.go b/src/cmd/internal/gc/gsubr.go
index ad5e494..48a24a6 100644
--- a/src/cmd/internal/gc/gsubr.go
+++ b/src/cmd/internal/gc/gsubr.go
@@ -274,8 +274,7 @@
}
}
-func Naddr(n *Node, a *obj.Addr, canemitcode int) {
- *a = obj.Addr{}
+func Naddr(n *Node, canemitcode int) (a obj.Addr) {
if n == nil {
return
}
@@ -294,7 +293,8 @@
switch n.Op {
default:
- Fatal("naddr: bad %v %v", Oconv(int(n.Op), 0), Ctxt.Dconv(a))
+ a := a // copy to let escape into Ctxt.Dconv
+ Fatal("naddr: bad %v %v", Oconv(int(n.Op), 0), Ctxt.Dconv(&a))
case OREGISTER:
a.Type = obj.TYPE_REG
@@ -338,7 +338,7 @@
a.Offset = n.Xoffset
case OCFUNC:
- Naddr(n.Left, a, canemitcode)
+ a = Naddr(n.Left, canemitcode)
a.Sym = Linksym(n.Left.Sym)
case ONAME:
@@ -408,7 +408,7 @@
a.Offset = Mpgetfix(n.Val.U.Xval)
case CTSTR:
- datagostring(n.Val.U.Sval, a)
+ datagostring(n.Val.U.Sval, &a)
case CTBOOL:
a.Sym = nil
@@ -422,19 +422,20 @@
}
case OADDR:
- Naddr(n.Left, a, canemitcode)
+ a = Naddr(n.Left, canemitcode)
a.Etype = uint8(Tptr)
if Thearch.Thechar != '5' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
a.Width = int64(Widthptr)
}
if a.Type != obj.TYPE_MEM {
- Fatal("naddr: OADDR %v (from %v)", Ctxt.Dconv(a), Oconv(int(n.Left.Op), 0))
+ a := a // copy to let escape into Ctxt.Dconv
+ Fatal("naddr: OADDR %v (from %v)", Ctxt.Dconv(&a), Oconv(int(n.Left.Op), 0))
}
a.Type = obj.TYPE_ADDR
// itable of interface value
case OITAB:
- Naddr(n.Left, a, canemitcode)
+ a = Naddr(n.Left, canemitcode)
if a.Type == obj.TYPE_CONST && a.Offset == 0 {
break // itab(nil)
@@ -444,7 +445,7 @@
// pointer in a string or slice
case OSPTR:
- Naddr(n.Left, a, canemitcode)
+ a = Naddr(n.Left, canemitcode)
if a.Type == obj.TYPE_CONST && a.Offset == 0 {
break // ptr(nil)
@@ -455,7 +456,7 @@
// len of string or slice
case OLEN:
- Naddr(n.Left, a, canemitcode)
+ a = Naddr(n.Left, canemitcode)
if a.Type == obj.TYPE_CONST && a.Offset == 0 {
break // len(nil)
@@ -471,7 +472,7 @@
// cap of string or slice
case OCAP:
- Naddr(n.Left, a, canemitcode)
+ a = Naddr(n.Left, canemitcode)
if a.Type == obj.TYPE_CONST && a.Offset == 0 {
break // cap(nil)
@@ -485,6 +486,7 @@
a.Width = int64(Widthint)
}
}
+ return
}
func newplist() *obj.Plist {
diff --git a/src/cmd/internal/gc/plive.go b/src/cmd/internal/gc/plive.go
index 5456435..ba13cdb 100644
--- a/src/cmd/internal/gc/plive.go
+++ b/src/cmd/internal/gc/plive.go
@@ -556,13 +556,11 @@
// initialized, because any use of a variable must come after its
// initialization.
func progeffects(prog *obj.Prog, vars []*Node, uevar *Bvec, varkill *Bvec, avarinit *Bvec) {
- var info ProgInfo
-
bvresetall(uevar)
bvresetall(varkill)
bvresetall(avarinit)
- info = Thearch.Proginfo(prog)
+ info := Thearch.Proginfo(prog)
if prog.As == obj.ARET {
// Return instructions implicitly read all the arguments. For
// the sake of correctness, out arguments must be read. For the
@@ -1087,8 +1085,8 @@
Nodconst(&to, Types[TINT32], int64(index))
pcdata := unlinkedprog(obj.APCDATA)
pcdata.Lineno = prog.Lineno
- Naddr(&from, &pcdata.From, 0)
- Naddr(&to, &pcdata.To, 0)
+ pcdata.From = Naddr(&from, 0)
+ pcdata.To = Naddr(&to, 0)
return pcdata
}
@@ -1296,7 +1294,6 @@
any := bvalloc(nvars)
all := bvalloc(nvars)
ambig := bvalloc(localswords() * obj.BitsPerPointer)
- var msg []string
nmsg := int32(0)
startmsg := int32(0)
@@ -1392,6 +1389,7 @@
var fmt_ string
var next *obj.Prog
var numlive int32
+ var msg []string
for i := int32(0); i < int32(len(lv.cfg)); i++ {
bb = lv.cfg[i]
diff --git a/src/cmd/internal/gc/range.go b/src/cmd/internal/gc/range.go
index ed50bdf..3de70ba 100644
--- a/src/cmd/internal/gc/range.go
+++ b/src/cmd/internal/gc/range.go
@@ -136,7 +136,6 @@
func walkrange(n *Node) {
t := n.Type
- var init *NodeList
a := n.Right
lno := int(setlineno(a))
@@ -154,9 +153,8 @@
// to avoid erroneous processing by racewalk.
n.List = nil
- var hv2 *Node
-
var body *NodeList
+ var init *NodeList
switch t.Etype {
default:
Fatal("walkrange")
@@ -366,6 +364,7 @@
init = list(init, Nod(OAS, hv1, nil))
var a *Node
+ var hv2 *Node
if v2 == nil {
a = Nod(OAS, hv1, mkcall("stringiter", Types[TINT], nil, ha, hv1))
} else {
diff --git a/src/cmd/internal/gc/typecheck.go b/src/cmd/internal/gc/typecheck.go
index 0ff8224..845aac6 100644
--- a/src/cmd/internal/gc/typecheck.go
+++ b/src/cmd/internal/gc/typecheck.go
@@ -276,44 +276,27 @@
}
func typecheck1(np **Node, top int) {
- var et int
- var aop int
- var op int
- var ptr int
- var l *Node
- var r *Node
- var lo *Node
- var mid *Node
- var hi *Node
- var ok int
- var ntop int
- var t *Type
- var tp *Type
- var missing *Type
- var have *Type
- var badtype *Type
- var v Val
- var why string
- var x int64
-
n := *np
+ defer func() {
+ *np = n
+ }()
if n.Sym != nil {
if n.Op == ONAME && n.Etype != 0 && top&Ecall == 0 {
Yyerror("use of builtin %v not in function call", Sconv(n.Sym, 0))
- goto error
+ n.Type = nil
+ return
}
typecheckdef(n)
if n.Op == ONONAME {
- goto error
+ n.Type = nil
+ return
}
}
- *np = n
-
-reswitch:
- ok = 0
+ ok := 0
+OpSwitch:
switch n.Op {
// until typecheck is complete, do nothing.
default:
@@ -330,11 +313,11 @@
if n.Type == nil && n.Val.Ctype == CTSTR {
n.Type = idealstring
}
- goto ret
+ break OpSwitch
case ONONAME:
ok |= Erv
- goto ret
+ break OpSwitch
case ONAME:
if n.Decldepth == 0 {
@@ -342,14 +325,15 @@
}
if n.Etype != 0 {
ok |= Ecall
- goto ret
+ break OpSwitch
}
if top&Easgn == 0 {
// not a write to the variable
if isblank(n) {
Yyerror("cannot use _ as value")
- goto error
+ n.Type = nil
+ return
}
n.Used = 1
@@ -357,15 +341,17 @@
if top&Ecall == 0 && isunsafebuiltin(n) {
Yyerror("%v is not an expression, must be called", Nconv(n, 0))
- goto error
+ n.Type = nil
+ return
}
ok |= Erv
- goto ret
+ break OpSwitch
case OPACK:
Yyerror("use of package %v without selector", Sconv(n.Sym, 0))
- goto error
+ n.Type = nil
+ return
case ODDD:
break
@@ -377,14 +363,15 @@
ok |= Etype
if n.Type == nil {
- goto error
+ n.Type = nil
+ return
}
case OTARRAY:
ok |= Etype
- t = typ(TARRAY)
- l = n.Left
- r = n.Right
+ t := typ(TARRAY)
+ l := n.Left
+ r := n.Right
if l == nil {
t.Bound = -1 // slice
} else if l.Op == ODDD {
@@ -395,7 +382,8 @@
Yyerror("use of [...] array outside of array literal")
}
} else {
- l = typecheck(&n.Left, Erv)
+ l := typecheck(&n.Left, Erv)
+ var v Val
switch consttype(l) {
case CTINT,
CTRUNE:
@@ -410,22 +398,26 @@
} else {
Yyerror("invalid array bound %v", Nconv(l, 0))
}
- goto error
+ n.Type = nil
+ return
}
t.Bound = Mpgetfix(v.U.Xval)
if doesoverflow(v, Types[TINT]) {
Yyerror("array bound is too large")
- goto error
+ n.Type = nil
+ return
} else if t.Bound < 0 {
Yyerror("array bound must be non-negative")
- goto error
+ n.Type = nil
+ return
}
}
typecheck(&r, Etype)
if r.Type == nil {
- goto error
+ n.Type = nil
+ return
}
t.Type = r.Type
n.Op = OTYPE
@@ -438,10 +430,11 @@
case OTMAP:
ok |= Etype
- l = typecheck(&n.Left, Etype)
- r = typecheck(&n.Right, Etype)
+ l := typecheck(&n.Left, Etype)
+ r := typecheck(&n.Right, Etype)
if l.Type == nil || r.Type == nil {
- goto error
+ n.Type = nil
+ return
}
n.Op = OTYPE
n.Type = maptype(l.Type, r.Type)
@@ -450,11 +443,12 @@
case OTCHAN:
ok |= Etype
- l = typecheck(&n.Left, Etype)
+ l := typecheck(&n.Left, Etype)
if l.Type == nil {
- goto error
+ n.Type = nil
+ return
}
- t = typ(TCHAN)
+ t := typ(TCHAN)
t.Type = l.Type
t.Chan = n.Etype
n.Op = OTYPE
@@ -467,7 +461,8 @@
n.Op = OTYPE
n.Type = tostruct(n.List)
if n.Type == nil || n.Type.Broke != 0 {
- goto error
+ n.Type = nil
+ return
}
n.List = nil
@@ -476,7 +471,8 @@
n.Op = OTYPE
n.Type = tointerface(n.List)
if n.Type == nil {
- goto error
+ n.Type = nil
+ return
}
case OTFUNC:
@@ -484,61 +480,53 @@
n.Op = OTYPE
n.Type = functype(n.Left, n.List, n.Rlist)
if n.Type == nil {
- goto error
+ n.Type = nil
+ return
}
/*
* type or expr
*/
case OIND:
- ntop = Erv | Etype
+ ntop := Erv | Etype
if top&Eaddr == 0 {
ntop |= Eindir
}
ntop |= top & Ecomplit
- l = typecheck(&n.Left, ntop)
- t = l.Type
+ l := typecheck(&n.Left, ntop)
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if l.Op == OTYPE {
ok |= Etype
n.Op = OTYPE
n.Type = Ptrto(l.Type)
n.Left = nil
- goto ret
+ break OpSwitch
}
if !Isptr[t.Etype] {
if top&(Erv|Etop) != 0 {
Yyerror("invalid indirect of %v", Nconv(n.Left, obj.FmtLong))
- goto error
+ n.Type = nil
+ return
}
- goto ret
+ break OpSwitch
}
ok |= Erv
n.Type = t.Type
- goto ret
+ break OpSwitch
/*
* arithmetic exprs
*/
- case OASOP:
- ok |= Etop
-
- l = typecheck(&n.Left, Erv)
- r = typecheck(&n.Right, Erv)
- checkassign(n, n.Left)
- if l.Type == nil || r.Type == nil {
- goto error
- }
- op = int(n.Etype)
- goto arith
-
- case OADD,
+ case OASOP,
+ OADD,
OAND,
OANDAND,
OANDNOT,
@@ -557,32 +545,270 @@
OOROR,
OSUB,
OXOR:
- ok |= Erv
- l = typecheck(&n.Left, Erv|top&Eiota)
- r = typecheck(&n.Right, Erv|top&Eiota)
- if l.Type == nil || r.Type == nil {
- goto error
+ var l *Node
+ var op int
+ var r *Node
+ if n.Op == OASOP {
+ ok |= Etop
+ l = typecheck(&n.Left, Erv)
+ r = typecheck(&n.Right, Erv)
+ checkassign(n, n.Left)
+ if l.Type == nil || r.Type == nil {
+ n.Type = nil
+ return
+ }
+ op = int(n.Etype)
+ } else {
+ ok |= Erv
+ l = typecheck(&n.Left, Erv|top&Eiota)
+ r = typecheck(&n.Right, Erv|top&Eiota)
+ if l.Type == nil || r.Type == nil {
+ n.Type = nil
+ return
+ }
+ op = int(n.Op)
}
- op = int(n.Op)
- goto arith
+ if op == OLSH || op == ORSH {
+ defaultlit(&r, Types[TUINT])
+ n.Right = r
+ t := r.Type
+ if !Isint[t.Etype] || Issigned[t.Etype] {
+ Yyerror("invalid operation: %v (shift count type %v, must be unsigned integer)", Nconv(n, 0), Tconv(r.Type, 0))
+ n.Type = nil
+ return
+ }
+
+ t = l.Type
+ if t != nil && t.Etype != TIDEAL && !Isint[t.Etype] {
+ Yyerror("invalid operation: %v (shift of type %v)", Nconv(n, 0), Tconv(t, 0))
+ n.Type = nil
+ return
+ }
+
+ // no defaultlit for left
+ // the outer context gives the type
+ n.Type = l.Type
+
+ break OpSwitch
+ }
+
+ // ideal mixed with non-ideal
+ defaultlit2(&l, &r, 0)
+
+ n.Left = l
+ n.Right = r
+ if l.Type == nil || r.Type == nil {
+ n.Type = nil
+ return
+ }
+ t := l.Type
+ if t.Etype == TIDEAL {
+ t = r.Type
+ }
+ et := int(t.Etype)
+ if et == TIDEAL {
+ et = TINT
+ }
+ aop := 0
+ if iscmp[n.Op] && t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
+ // comparison is okay as long as one side is
+ // assignable to the other. convert so they have
+ // the same type.
+ //
+ // the only conversion that isn't a no-op is concrete == interface.
+ // in that case, check comparability of the concrete type.
+ // The conversion allocates, so only do it if the concrete type is huge.
+ if r.Type.Etype != TBLANK {
+ aop = assignop(l.Type, r.Type, nil)
+ if aop != 0 {
+ if Isinter(r.Type) && !Isinter(l.Type) && algtype1(l.Type, nil) == ANOEQ {
+ Yyerror("invalid operation: %v (operator %v not defined on %s)", Nconv(n, 0), Oconv(int(op), 0), typekind(l.Type))
+ n.Type = nil
+ return
+ }
+
+ dowidth(l.Type)
+ if Isinter(r.Type) == Isinter(l.Type) || l.Type.Width >= 1<<16 {
+ l = Nod(aop, l, nil)
+ l.Type = r.Type
+ l.Typecheck = 1
+ n.Left = l
+ }
+
+ t = r.Type
+ goto converted
+ }
+ }
+
+ if l.Type.Etype != TBLANK {
+ aop = assignop(r.Type, l.Type, nil)
+ if aop != 0 {
+ if Isinter(l.Type) && !Isinter(r.Type) && algtype1(r.Type, nil) == ANOEQ {
+ Yyerror("invalid operation: %v (operator %v not defined on %s)", Nconv(n, 0), Oconv(int(op), 0), typekind(r.Type))
+ n.Type = nil
+ return
+ }
+
+ dowidth(r.Type)
+ if Isinter(r.Type) == Isinter(l.Type) || r.Type.Width >= 1<<16 {
+ r = Nod(aop, r, nil)
+ r.Type = l.Type
+ r.Typecheck = 1
+ n.Right = r
+ }
+
+ t = l.Type
+ }
+ }
+
+ converted:
+ et = int(t.Etype)
+ }
+
+ if t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
+ defaultlit2(&l, &r, 1)
+ if n.Op == OASOP && n.Implicit != 0 {
+ Yyerror("invalid operation: %v (non-numeric type %v)", Nconv(n, 0), Tconv(l.Type, 0))
+ n.Type = nil
+ return
+ }
+
+ if Isinter(r.Type) == Isinter(l.Type) || aop == 0 {
+ Yyerror("invalid operation: %v (mismatched types %v and %v)", Nconv(n, 0), Tconv(l.Type, 0), Tconv(r.Type, 0))
+ n.Type = nil
+ return
+ }
+ }
+
+ if !okfor[op][et] {
+ Yyerror("invalid operation: %v (operator %v not defined on %s)", Nconv(n, 0), Oconv(int(op), 0), typekind(t))
+ n.Type = nil
+ return
+ }
+
+ // okfor allows any array == array, map == map, func == func.
+ // restrict to slice/map/func == nil and nil == slice/map/func.
+ if Isfixedarray(l.Type) && algtype1(l.Type, nil) == ANOEQ {
+ Yyerror("invalid operation: %v (%v cannot be compared)", Nconv(n, 0), Tconv(l.Type, 0))
+ n.Type = nil
+ return
+ }
+
+ if Isslice(l.Type) && !isnil(l) && !isnil(r) {
+ Yyerror("invalid operation: %v (slice can only be compared to nil)", Nconv(n, 0))
+ n.Type = nil
+ return
+ }
+
+ if l.Type.Etype == TMAP && !isnil(l) && !isnil(r) {
+ Yyerror("invalid operation: %v (map can only be compared to nil)", Nconv(n, 0))
+ n.Type = nil
+ return
+ }
+
+ if l.Type.Etype == TFUNC && !isnil(l) && !isnil(r) {
+ Yyerror("invalid operation: %v (func can only be compared to nil)", Nconv(n, 0))
+ n.Type = nil
+ return
+ }
+
+ var badtype *Type
+ if l.Type.Etype == TSTRUCT && algtype1(l.Type, &badtype) == ANOEQ {
+ Yyerror("invalid operation: %v (struct containing %v cannot be compared)", Nconv(n, 0), Tconv(badtype, 0))
+ n.Type = nil
+ return
+ }
+
+ t = l.Type
+ if iscmp[n.Op] {
+ evconst(n)
+ t = idealbool
+ if n.Op != OLITERAL {
+ defaultlit2(&l, &r, 1)
+ n.Left = l
+ n.Right = r
+ }
+ } else if n.Op == OANDAND || n.Op == OOROR {
+ if l.Type == r.Type {
+ t = l.Type
+ } else if l.Type == idealbool {
+ t = r.Type
+ } else if r.Type == idealbool {
+ t = l.Type
+ }
+ } else
+ // non-comparison operators on ideal bools should make them lose their ideal-ness
+ if t == idealbool {
+ t = Types[TBOOL]
+ }
+
+ if et == TSTRING {
+ if iscmp[n.Op] {
+ n.Etype = n.Op
+ n.Op = OCMPSTR
+ } else if n.Op == OADD {
+ // create OADDSTR node with list of strings in x + y + z + (w + v) + ...
+ n.Op = OADDSTR
+
+ if l.Op == OADDSTR {
+ n.List = l.List
+ } else {
+ n.List = list1(l)
+ }
+ if r.Op == OADDSTR {
+ n.List = concat(n.List, r.List)
+ } else {
+ n.List = list(n.List, r)
+ }
+ n.Left = nil
+ n.Right = nil
+ }
+ }
+
+ if et == TINTER {
+ if l.Op == OLITERAL && l.Val.Ctype == CTNIL {
+ // swap for back end
+ n.Left = r
+
+ n.Right = l
+ } else if r.Op == OLITERAL && r.Val.Ctype == CTNIL {
+ } else // leave alone for back end
+ if Isinter(r.Type) == Isinter(l.Type) {
+ n.Etype = n.Op
+ n.Op = OCMPIFACE
+ }
+ }
+
+ if (op == ODIV || op == OMOD) && Isconst(r, CTINT) {
+ if mpcmpfixc(r.Val.U.Xval, 0) == 0 {
+ Yyerror("division by zero")
+ n.Type = nil
+ return
+ }
+ }
+
+ n.Type = t
+ break OpSwitch
case OCOM,
OMINUS,
ONOT,
OPLUS:
ok |= Erv
- l = typecheck(&n.Left, Erv|top&Eiota)
- t = l.Type
+ l := typecheck(&n.Left, Erv|top&Eiota)
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if !okfor[n.Op][t.Etype] {
Yyerror("invalid operation: %v %v", Oconv(int(n.Op), 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
n.Type = t
- goto ret
+ break OpSwitch
/*
* exprs
@@ -592,10 +818,12 @@
typecheck(&n.Left, Erv|Eaddr)
if n.Left.Type == nil {
- goto error
+ n.Type = nil
+ return
}
checklvalue(n.Left, "take the address of")
- r = outervalue(n.Left)
+ r := outervalue(n.Left)
+ var l *Node
for l = n.Left; l != r; l = l.Left {
l.Addrtaken = 1
if l.Closure != nil {
@@ -612,46 +840,50 @@
}
defaultlit(&n.Left, nil)
l = n.Left
- t = l.Type
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
n.Type = Ptrto(t)
- goto ret
+ break OpSwitch
case OCOMPLIT:
ok |= Erv
typecheckcomplit(&n)
if n.Type == nil {
- goto error
+ n.Type = nil
+ return
}
- goto ret
+ break OpSwitch
- case OXDOT:
- n = adddot(n)
- n.Op = ODOT
- if n.Left == nil {
- goto error
+ case OXDOT, ODOT:
+ if n.Op == OXDOT {
+ n = adddot(n)
+ n.Op = ODOT
+ if n.Left == nil {
+ n.Type = nil
+ return
+ }
}
- fallthrough
- // fall through
- case ODOT:
typecheck(&n.Left, Erv|Etype)
defaultlit(&n.Left, nil)
if n.Right.Op != ONAME {
Yyerror("rhs of . must be a name") // impossible
- goto error
+ n.Type = nil
+ return
}
- t = n.Left.Type
+ t := n.Left.Type
if t == nil {
adderrorname(n)
- goto error
+ n.Type = nil
+ return
}
- r = n.Right
+ r := n.Right
if n.Left.Op == OTYPE {
if !looktypedot(n, t, 0) {
@@ -660,13 +892,15 @@
} else {
Yyerror("%v undefined (type %v has no method %v)", Nconv(n, 0), Tconv(t, 0), Sconv(n.Right.Sym, 0))
}
- goto error
+ n.Type = nil
+ return
}
if n.Type.Etype != TFUNC || n.Type.Thistuple != 1 {
Yyerror("type %v has no method %v", Tconv(n.Left.Type, 0), Sconv(n.Right.Sym, obj.FmtShort))
n.Type = nil
- goto error
+ n.Type = nil
+ return
}
n.Op = ONAME
@@ -675,13 +909,14 @@
n.Xoffset = 0
n.Class = PFUNC
ok = Erv
- goto ret
+ break OpSwitch
}
if Isptr[t.Etype] && t.Type.Etype != TINTER {
t = t.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
n.Op = ODOTPTR
checkwidth(t)
@@ -689,7 +924,8 @@
if isblank(n.Right) {
Yyerror("cannot refer to blank field or method")
- goto error
+ n.Type = nil
+ return
}
if !lookdot(n, t, 0) {
@@ -698,7 +934,8 @@
} else {
Yyerror("%v undefined (type %v has no field or method %v)", Nconv(n, 0), Tconv(n.Left.Type, 0), Sconv(n.Right.Sym, 0))
}
- goto error
+ n.Type = nil
+ return
}
switch n.Op {
@@ -715,20 +952,22 @@
ok |= Erv
}
- goto ret
+ break OpSwitch
case ODOTTYPE:
ok |= Erv
typecheck(&n.Left, Erv)
defaultlit(&n.Left, nil)
- l = n.Left
- t = l.Type
+ l := n.Left
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if !Isinter(t) {
Yyerror("invalid type assertion: %v (non-interface type %v on left)", Nconv(n, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
if n.Right != nil {
@@ -736,11 +975,15 @@
n.Type = n.Right.Type
n.Right = nil
if n.Type == nil {
- goto error
+ n.Type = nil
+ return
}
}
if n.Type != nil && n.Type.Etype != TINTER {
+ var have *Type
+ var missing *Type
+ var ptr int
if !implements(n.Type, t, &missing, &have, &ptr) {
if have != nil && have.Sym == missing.Sym {
Yyerror("impossible type assertion:\n\t%v does not implement %v (wrong type for %v method)\n"+"\t\thave %v%v\n\t\twant %v%v", Tconv(n.Type, 0), Tconv(t, 0), Sconv(missing.Sym, 0), Sconv(have.Sym, 0), Tconv(have.Type, obj.FmtShort|obj.FmtByte), Sconv(missing.Sym, 0), Tconv(missing.Type, obj.FmtShort|obj.FmtByte))
@@ -751,28 +994,31 @@
} else {
Yyerror("impossible type assertion:\n\t%v does not implement %v (missing %v method)", Tconv(n.Type, 0), Tconv(t, 0), Sconv(missing.Sym, 0))
}
- goto error
+ n.Type = nil
+ return
}
}
- goto ret
+ break OpSwitch
case OINDEX:
ok |= Erv
typecheck(&n.Left, Erv)
defaultlit(&n.Left, nil)
implicitstar(&n.Left)
- l = n.Left
+ l := n.Left
typecheck(&n.Right, Erv)
- r = n.Right
- t = l.Type
+ r := n.Right
+ t := l.Type
if t == nil || r.Type == nil {
- goto error
+ n.Type = nil
+ return
}
switch t.Etype {
default:
Yyerror("invalid operation: %v (type %v does not support indexing)", Nconv(n, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
case TSTRING,
TARRAY:
@@ -782,7 +1028,7 @@
} else {
n.Type = t.Type
}
- why = "string"
+ why := "string"
if t.Etype == TARRAY {
if Isfixedarray(t) {
why = "array"
@@ -797,7 +1043,7 @@
}
if Isconst(n.Right, CTINT) {
- x = Mpgetfix(n.Right.Val.U.Xval)
+ x := Mpgetfix(n.Right.Val.U.Xval)
if x < 0 {
Yyerror("invalid %s index %v (index must be non-negative)", why, Nconv(n.Right, 0))
} else if Isfixedarray(t) && t.Bound > 0 && x >= t.Bound {
@@ -819,54 +1065,61 @@
n.Op = OINDEXMAP
}
- goto ret
+ break OpSwitch
case ORECV:
ok |= Etop | Erv
typecheck(&n.Left, Erv)
defaultlit(&n.Left, nil)
- l = n.Left
- t = l.Type
+ l := n.Left
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if t.Etype != TCHAN {
Yyerror("invalid operation: %v (receive from non-chan type %v)", Nconv(n, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
if t.Chan&Crecv == 0 {
Yyerror("invalid operation: %v (receive from send-only type %v)", Nconv(n, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
n.Type = t.Type
- goto ret
+ break OpSwitch
case OSEND:
ok |= Etop
- l = typecheck(&n.Left, Erv)
+ l := typecheck(&n.Left, Erv)
typecheck(&n.Right, Erv)
defaultlit(&n.Left, nil)
l = n.Left
- t = l.Type
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if t.Etype != TCHAN {
Yyerror("invalid operation: %v (send to non-chan type %v)", Nconv(n, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
if t.Chan&Csend == 0 {
Yyerror("invalid operation: %v (send to receive-only type %v)", Nconv(n, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
defaultlit(&n.Right, t.Type)
- r = n.Right
+ r := n.Right
if r.Type == nil {
- goto error
+ n.Type = nil
+ return
}
n.Right = assignconv(r, l.Type.Type, "send")
@@ -874,7 +1127,7 @@
n.Etype = 0
n.Type = nil
- goto ret
+ break OpSwitch
case OSLICE:
ok |= Erv
@@ -884,11 +1137,12 @@
defaultlit(&n.Left, nil)
indexlit(&n.Right.Left)
indexlit(&n.Right.Right)
- l = n.Left
+ l := n.Left
if Isfixedarray(l.Type) {
if !islvalue(n.Left) {
Yyerror("invalid operation %v (slice of unaddressable value)", Nconv(n, 0))
- goto error
+ n.Type = nil
+ return
}
n.Left = Nod(OADDR, n.Left, nil)
@@ -897,11 +1151,12 @@
l = n.Left
}
- t = l.Type
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
- tp = nil
+ var tp *Type
if Istype(t, TSTRING) {
n.Type = t
n.Op = OSLICESTR
@@ -916,21 +1171,25 @@
n.Type = t
} else {
Yyerror("cannot slice %v (type %v)", Nconv(l, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
- lo = n.Right.Left
+ lo := n.Right.Left
if lo != nil && checksliceindex(l, lo, tp) < 0 {
- goto error
+ n.Type = nil
+ return
}
- hi = n.Right.Right
+ hi := n.Right.Right
if hi != nil && checksliceindex(l, hi, tp) < 0 {
- goto error
+ n.Type = nil
+ return
}
if checksliceconst(lo, hi) < 0 {
- goto error
+ n.Type = nil
+ return
}
- goto ret
+ break OpSwitch
case OSLICE3:
ok |= Erv
@@ -942,11 +1201,12 @@
indexlit(&n.Right.Left)
indexlit(&n.Right.Right.Left)
indexlit(&n.Right.Right.Right)
- l = n.Left
+ l := n.Left
if Isfixedarray(l.Type) {
if !islvalue(n.Left) {
Yyerror("invalid operation %v (slice of unaddressable value)", Nconv(n, 0))
- goto error
+ n.Type = nil
+ return
}
n.Left = Nod(OADDR, n.Left, nil)
@@ -955,16 +1215,18 @@
l = n.Left
}
- t = l.Type
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
- tp = nil
if Istype(t, TSTRING) {
Yyerror("invalid operation %v (3-index slice of string)", Nconv(n, 0))
- goto error
+ n.Type = nil
+ return
}
+ var tp *Type
if Isptr[t.Etype] && Isfixedarray(t.Type) {
tp = t.Type
n.Type = typ(TARRAY)
@@ -976,40 +1238,46 @@
n.Type = t
} else {
Yyerror("cannot slice %v (type %v)", Nconv(l, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
- lo = n.Right.Left
+ lo := n.Right.Left
if lo != nil && checksliceindex(l, lo, tp) < 0 {
- goto error
+ n.Type = nil
+ return
}
- mid = n.Right.Right.Left
+ mid := n.Right.Right.Left
if mid != nil && checksliceindex(l, mid, tp) < 0 {
- goto error
+ n.Type = nil
+ return
}
- hi = n.Right.Right.Right
+ hi := n.Right.Right.Right
if hi != nil && checksliceindex(l, hi, tp) < 0 {
- goto error
+ n.Type = nil
+ return
}
if checksliceconst(lo, hi) < 0 || checksliceconst(lo, mid) < 0 || checksliceconst(mid, hi) < 0 {
- goto error
+ n.Type = nil
+ return
}
- goto ret
+ break OpSwitch
/*
* call and call like
*/
case OCALL:
- l = n.Left
+ l := n.Left
if l.Op == ONAME {
- r = unsafenmagic(n)
+ r := unsafenmagic(n)
if r != nil {
if n.Isddd != 0 {
Yyerror("invalid use of ... with builtin %v", Nconv(l, 0))
}
n = r
- goto reswitch
+ typecheck1(&n, top)
+ return
}
}
@@ -1026,11 +1294,12 @@
n.Left = n.Right
n.Right = nil
- goto reswitch
+ typecheck1(&n, top)
+ return
}
defaultlit(&n.Left, nil)
- l := n.Left
+ l = n.Left
if l.Op == OTYPE {
if n.Isddd != 0 || l.Type.Bound == -100 {
if l.Type.Broke == 0 {
@@ -1048,9 +1317,11 @@
n.Op = OCONV
n.Type = l.Type
if onearg(n, "conversion to %v", Tconv(l.Type, 0)) < 0 {
- goto error
+ n.Type = nil
+ return
}
- goto doconv
+ typecheck1(&n, top)
+ return
}
if count(n.List) == 1 && n.Isddd == 0 {
@@ -1060,7 +1331,8 @@
}
t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
checkwidth(t)
@@ -1085,7 +1357,8 @@
n.Op = OCALLFUNC
if t.Etype != TFUNC {
Yyerror("cannot call non-function %v (type %v)", Nconv(l, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
}
@@ -1094,29 +1367,30 @@
typecheckaste(OCALL, n.Left, int(n.Isddd), getinargx(t), n.List, desc)
ok |= Etop
if t.Outtuple == 0 {
- goto ret
+ break OpSwitch
}
ok |= Erv
if t.Outtuple == 1 {
t := getoutargx(l.Type).Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if t.Etype == TFIELD {
t = t.Type
}
n.Type = t
- goto ret
+ break OpSwitch
}
// multiple return
if top&(Efnstruct|Etop) == 0 {
Yyerror("multiple-value %v() in single-value context", Nconv(l, 0))
- goto ret
+ break OpSwitch
}
n.Type = getoutargx(l.Type)
- goto ret
+ break OpSwitch
case OCAP,
OLEN,
@@ -1124,7 +1398,8 @@
OIMAG:
ok |= Erv
if onearg(n, "%v", Oconv(int(n.Op), 0)) < 0 {
- goto error
+ n.Type = nil
+ return
}
typecheck(&n.Left, Erv)
defaultlit(&n.Left, nil)
@@ -1132,7 +1407,8 @@
l := n.Left
t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
switch n.Op {
case OCAP:
@@ -1161,7 +1437,7 @@
}
n.Type = Types[cplxsubtype(int(t.Etype))]
- goto ret
+ break OpSwitch
}
// might be constant
@@ -1188,7 +1464,12 @@
}
n.Type = Types[TINT]
- goto ret
+ break OpSwitch
+
+ badcall1:
+ Yyerror("invalid argument %v for %v", Nconv(n.Left, obj.FmtLong), Oconv(int(n.Op), 0))
+ n.Type = nil
+ return
case OCOMPLEX:
ok |= Erv
@@ -1198,13 +1479,15 @@
typechecklist(n.List, Efnstruct)
if n.List.N.Op != OCALLFUNC && n.List.N.Op != OCALLMETH {
Yyerror("invalid operation: complex expects two arguments")
- goto error
+ n.Type = nil
+ return
}
t := n.List.N.Left.Type
if t.Outtuple != 2 {
Yyerror("invalid operation: complex expects two arguments, %v returns %d results", Nconv(n.List.N, 0), t.Outtuple)
- goto error
+ n.Type = nil
+ return
}
t = n.List.N.Type.Type
@@ -1212,16 +1495,19 @@
r = t.Down.Nname
} else {
if twoarg(n) < 0 {
- goto error
+ n.Type = nil
+ return
}
l = typecheck(&n.Left, Erv|top&Eiota)
r = typecheck(&n.Right, Erv|top&Eiota)
if l.Type == nil || r.Type == nil {
- goto error
+ n.Type = nil
+ return
}
defaultlit2(&l, &r, 0)
if l.Type == nil || r.Type == nil {
- goto error
+ n.Type = nil
+ return
}
n.Left = l
n.Right = r
@@ -1229,14 +1515,16 @@
if !Eqtype(l.Type, r.Type) {
Yyerror("invalid operation: %v (mismatched types %v and %v)", Nconv(n, 0), Tconv(l.Type, 0), Tconv(r.Type, 0))
- goto error
+ n.Type = nil
+ return
}
var t *Type
switch l.Type.Etype {
default:
Yyerror("invalid operation: %v (arguments have type %v, expected floating-point)", Nconv(n, 0), Tconv(l.Type, 0), r.Type)
- goto error
+ n.Type = nil
+ return
case TIDEAL:
t = Types[TIDEAL]
@@ -1257,47 +1545,54 @@
}
n.Type = t
- goto ret
+ break OpSwitch
case OCLOSE:
if onearg(n, "%v", Oconv(int(n.Op), 0)) < 0 {
- goto error
+ n.Type = nil
+ return
}
typecheck(&n.Left, Erv)
defaultlit(&n.Left, nil)
l := n.Left
t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if t.Etype != TCHAN {
Yyerror("invalid operation: %v (non-chan type %v)", Nconv(n, 0), Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
if t.Chan&Csend == 0 {
Yyerror("invalid operation: %v (cannot close receive-only channel)", Nconv(n, 0))
- goto error
+ n.Type = nil
+ return
}
ok |= Etop
- goto ret
+ break OpSwitch
case ODELETE:
args := n.List
if args == nil {
Yyerror("missing arguments to delete")
- goto error
+ n.Type = nil
+ return
}
if args.Next == nil {
Yyerror("missing second (key) argument to delete")
- goto error
+ n.Type = nil
+ return
}
if args.Next.Next != nil {
Yyerror("too many arguments to delete")
- goto error
+ n.Type = nil
+ return
}
ok |= Etop
@@ -1306,18 +1601,20 @@
r := args.Next.N
if l.Type != nil && l.Type.Etype != TMAP {
Yyerror("first argument to delete must be map; have %v", Tconv(l.Type, obj.FmtLong))
- goto error
+ n.Type = nil
+ return
}
args.Next.N = assignconv(r, l.Type.Down, "delete")
- goto ret
+ break OpSwitch
case OAPPEND:
ok |= Erv
args := n.List
if args == nil {
Yyerror("missing arguments to append")
- goto error
+ n.Type = nil
+ return
}
if count(args) == 1 && n.Isddd == 0 {
@@ -1328,7 +1625,8 @@
t := args.N.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
// Unpack multiple-return result before type-checking.
@@ -1343,31 +1641,35 @@
if !Isslice(t) {
if Isconst(args.N, CTNIL) {
Yyerror("first argument to append must be typed slice; have untyped nil", t)
- goto error
+ n.Type = nil
+ return
}
Yyerror("first argument to append must be slice; have %v", Tconv(t, obj.FmtLong))
- goto error
+ n.Type = nil
+ return
}
if n.Isddd != 0 {
if args.Next == nil {
Yyerror("cannot use ... on first argument to append")
- goto error
+ n.Type = nil
+ return
}
if args.Next.Next != nil {
Yyerror("too many arguments to append")
- goto error
+ n.Type = nil
+ return
}
if Istype(t.Type, TUINT8) && Istype(args.Next.N.Type, TSTRING) {
defaultlit(&args.Next.N, Types[TSTRING])
- goto ret
+ break OpSwitch
}
args.Next.N = assignconv(args.Next.N, t.Orig, "append")
- goto ret
+ break OpSwitch
}
for args = args.Next; args != nil; args = args.Next {
@@ -1377,19 +1679,21 @@
args.N = assignconv(args.N, t.Type, "append")
}
- goto ret
+ break OpSwitch
case OCOPY:
ok |= Etop | Erv
args := n.List
if args == nil || args.Next == nil {
Yyerror("missing arguments to copy")
- goto error
+ n.Type = nil
+ return
}
if args.Next.Next != nil {
Yyerror("too many arguments to copy")
- goto error
+ n.Type = nil
+ return
}
n.Left = args.N
@@ -1399,21 +1703,24 @@
typecheck(&n.Left, Erv)
typecheck(&n.Right, Erv)
if n.Left.Type == nil || n.Right.Type == nil {
- goto error
+ n.Type = nil
+ return
}
defaultlit(&n.Left, nil)
defaultlit(&n.Right, nil)
if n.Left.Type == nil || n.Right.Type == nil {
- goto error
+ n.Type = nil
+ return
}
// copy([]byte, string)
if Isslice(n.Left.Type) && n.Right.Type.Etype == TSTRING {
if Eqtype(n.Left.Type.Type, bytetype) {
- goto ret
+ break OpSwitch
}
Yyerror("arguments to copy have different element types: %v and string", Tconv(n.Left.Type, obj.FmtLong))
- goto error
+ n.Type = nil
+ return
}
if !Isslice(n.Left.Type) || !Isslice(n.Right.Type) {
@@ -1424,25 +1731,73 @@
} else {
Yyerror("second argument to copy should be slice or string; have %v", Tconv(n.Right.Type, obj.FmtLong))
}
- goto error
+ n.Type = nil
+ return
}
if !Eqtype(n.Left.Type.Type, n.Right.Type.Type) {
Yyerror("arguments to copy have different element types: %v and %v", Tconv(n.Left.Type, obj.FmtLong), Tconv(n.Right.Type, obj.FmtLong))
- goto error
+ n.Type = nil
+ return
}
- goto ret
+ break OpSwitch
case OCONV:
- goto doconv
+ {
+ ok |= Erv
+ saveorignode(n)
+ typecheck(&n.Left, Erv|top&(Eindir|Eiota))
+ convlit1(&n.Left, n.Type, true)
+ t := n.Left.Type
+ if t == nil || n.Type == nil {
+ n.Type = nil
+ return
+ }
+ var why string
+ n.Op = uint8(convertop(t, n.Type, &why))
+ if (n.Op) == 0 {
+ if n.Diag == 0 && n.Type.Broke == 0 {
+ Yyerror("cannot convert %v to type %v%s", Nconv(n.Left, obj.FmtLong), Tconv(n.Type, 0), why)
+ n.Diag = 1
+ }
+
+ n.Op = OCONV
+ }
+
+ switch n.Op {
+ case OCONVNOP:
+ if n.Left.Op == OLITERAL && n.Type != Types[TBOOL] {
+ r := Nod(OXXX, nil, nil)
+ n.Op = OCONV
+ n.Orig = r
+ *r = *n
+ n.Op = OLITERAL
+ n.Val = n.Left.Val
+ }
+
+ // do not use stringtoarraylit.
+ // generated code and compiler memory footprint is better without it.
+ case OSTRARRAYBYTE:
+ break
+
+ case OSTRARRAYRUNE:
+ if n.Left.Op == OLITERAL {
+ stringtoarraylit(&n)
+ }
+ }
+
+ break OpSwitch
+ }
+ break OpSwitch
case OMAKE:
ok |= Erv
args := n.List
if args == nil {
Yyerror("missing argument to make")
- goto error
+ n.Type = nil
+ return
}
n.List = nil
@@ -1451,23 +1806,27 @@
typecheck(&l, Etype)
t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
switch t.Etype {
default:
Yyerror("cannot make type %v", Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
case TARRAY:
if !Isslice(t) {
Yyerror("cannot make type %v", Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
if args == nil {
Yyerror("missing len argument to make(%v)", Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
l = args.N
@@ -1481,16 +1840,19 @@
}
if l.Type == nil || (r != nil && r.Type == nil) {
- goto error
+ n.Type = nil
+ return
}
et := bool2int(checkmake(t, "len", l) < 0)
et |= bool2int(r != nil && checkmake(t, "cap", r) < 0)
if et != 0 {
- goto error
+ n.Type = nil
+ return
}
if Isconst(l, CTINT) && r != nil && Isconst(r, CTINT) && Mpcmpfixfix(l.Val.U.Xval, r.Val.U.Xval) > 0 {
Yyerror("len larger than cap in make(%v)", Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
n.Left = l
@@ -1504,10 +1866,12 @@
typecheck(&l, Erv)
defaultlit(&l, Types[TINT])
if l.Type == nil {
- goto error
+ n.Type = nil
+ return
}
if checkmake(t, "size", l) < 0 {
- goto error
+ n.Type = nil
+ return
}
n.Left = l
} else {
@@ -1523,10 +1887,12 @@
typecheck(&l, Erv)
defaultlit(&l, Types[TINT])
if l.Type == nil {
- goto error
+ n.Type = nil
+ return
}
if checkmake(t, "buffer", l) < 0 {
- goto error
+ n.Type = nil
+ return
}
n.Left = l
} else {
@@ -1538,34 +1904,38 @@
if args != nil {
Yyerror("too many arguments to make(%v)", Tconv(t, 0))
n.Op = OMAKE
- goto error
+ n.Type = nil
+ return
}
n.Type = t
- goto ret
+ break OpSwitch
case ONEW:
ok |= Erv
args := n.List
if args == nil {
Yyerror("missing argument to new")
- goto error
+ n.Type = nil
+ return
}
l := args.N
typecheck(&l, Etype)
t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if args.Next != nil {
Yyerror("too many arguments to new(%v)", Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
n.Left = l
n.Type = Ptrto(t)
- goto ret
+ break OpSwitch
case OPRINT,
OPRINTN:
@@ -1580,57 +1950,63 @@
}
}
- goto ret
+ break OpSwitch
case OPANIC:
ok |= Etop
if onearg(n, "panic") < 0 {
- goto error
+ n.Type = nil
+ return
}
typecheck(&n.Left, Erv)
defaultlit(&n.Left, Types[TINTER])
if n.Left.Type == nil {
- goto error
+ n.Type = nil
+ return
}
- goto ret
+ break OpSwitch
case ORECOVER:
ok |= Erv | Etop
if n.List != nil {
Yyerror("too many arguments to recover")
- goto error
+ n.Type = nil
+ return
}
n.Type = Types[TINTER]
- goto ret
+ break OpSwitch
case OCLOSURE:
ok |= Erv
typecheckclosure(n, top)
if n.Type == nil {
- goto error
+ n.Type = nil
+ return
}
- goto ret
+ break OpSwitch
case OITAB:
ok |= Erv
typecheck(&n.Left, Erv)
t := n.Left.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if t.Etype != TINTER {
Fatal("OITAB of %v", Tconv(t, 0))
}
n.Type = Ptrto(Types[TUINTPTR])
- goto ret
+ break OpSwitch
case OSPTR:
ok |= Erv
typecheck(&n.Left, Erv)
t := n.Left.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
if !Isslice(t) && t.Etype != TSTRING {
Fatal("OSPTR of %v", Tconv(t, 0))
@@ -1640,22 +2016,22 @@
} else {
n.Type = Ptrto(t.Type)
}
- goto ret
+ break OpSwitch
case OCLOSUREVAR:
ok |= Erv
- goto ret
+ break OpSwitch
case OCFUNC:
ok |= Erv
typecheck(&n.Left, Erv)
n.Type = Types[TUINTPTR]
- goto ret
+ break OpSwitch
case OCONVNOP:
ok |= Erv
typecheck(&n.Left, Erv)
- goto ret
+ break OpSwitch
/*
* statements
@@ -1669,12 +2045,12 @@
if n.Left.Op == ONAME && strings.HasPrefix(n.Left.Sym.Name, "autotmp_") {
n.Left.Defn = n
}
- goto ret
+ break OpSwitch
case OAS2:
ok |= Etop
typecheckas2(n)
- goto ret
+ break OpSwitch
case OBREAK,
OCONTINUE,
@@ -1684,12 +2060,12 @@
OXFALL,
OVARKILL:
ok |= Etop
- goto ret
+ break OpSwitch
case OLABEL:
ok |= Etop
decldepth++
- goto ret
+ break OpSwitch
case ODEFER:
ok |= Etop
@@ -1697,13 +2073,13 @@
if n.Left.Diag == 0 {
checkdefergo(n)
}
- goto ret
+ break OpSwitch
case OPROC:
ok |= Etop
typecheck(&n.Left, Etop|Eproc|Erv)
checkdefergo(n)
- goto ret
+ break OpSwitch
case OFOR:
ok |= Etop
@@ -1719,7 +2095,7 @@
typecheck(&n.Nincr, Etop)
typechecklist(n.Nbody, Etop)
decldepth--
- goto ret
+ break OpSwitch
case OIF:
ok |= Etop
@@ -1733,7 +2109,7 @@
}
typechecklist(n.Nbody, Etop)
typechecklist(n.Nelse, Etop)
- goto ret
+ break OpSwitch
case ORETURN:
ok |= Etop
@@ -1744,53 +2120,55 @@
}
if Curfn == nil {
Yyerror("return outside function")
- goto error
+ n.Type = nil
+ return
}
if Curfn.Type.Outnamed != 0 && n.List == nil {
- goto ret
+ break OpSwitch
}
typecheckaste(ORETURN, nil, 0, getoutargx(Curfn.Type), n.List, "return argument")
- goto ret
+ break OpSwitch
case ORETJMP:
ok |= Etop
- goto ret
+ break OpSwitch
case OSELECT:
ok |= Etop
typecheckselect(n)
- goto ret
+ break OpSwitch
case OSWITCH:
ok |= Etop
typecheckswitch(n)
- goto ret
+ break OpSwitch
case ORANGE:
ok |= Etop
typecheckrange(n)
- goto ret
+ break OpSwitch
case OTYPESW:
Yyerror("use of .(type) outside type switch")
- goto error
+ n.Type = nil
+ return
case OXCASE:
ok |= Etop
typechecklist(n.List, Erv)
typechecklist(n.Nbody, Etop)
- goto ret
+ break OpSwitch
case ODCLFUNC:
ok |= Etop
typecheckfunc(n)
- goto ret
+ break OpSwitch
case ODCLCONST:
ok |= Etop
typecheck(&n.Left, Erv)
- goto ret
+ break OpSwitch
case ODCLTYPE:
ok |= Etop
@@ -1798,264 +2176,10 @@
if incannedimport == 0 {
checkwidth(n.Left.Type)
}
- goto ret
+ break OpSwitch
}
- goto ret
-
-arith:
- if op == OLSH || op == ORSH {
- defaultlit(&r, Types[TUINT])
- n.Right = r
- t := r.Type
- if !Isint[t.Etype] || Issigned[t.Etype] {
- Yyerror("invalid operation: %v (shift count type %v, must be unsigned integer)", Nconv(n, 0), Tconv(r.Type, 0))
- goto error
- }
-
- t = l.Type
- if t != nil && t.Etype != TIDEAL && !Isint[t.Etype] {
- Yyerror("invalid operation: %v (shift of type %v)", Nconv(n, 0), Tconv(t, 0))
- goto error
- }
-
- // no defaultlit for left
- // the outer context gives the type
- n.Type = l.Type
-
- goto ret
- }
-
- // ideal mixed with non-ideal
- defaultlit2(&l, &r, 0)
-
- n.Left = l
- n.Right = r
- if l.Type == nil || r.Type == nil {
- goto error
- }
- t = l.Type
- if t.Etype == TIDEAL {
- t = r.Type
- }
- et = int(t.Etype)
- if et == TIDEAL {
- et = TINT
- }
- aop = 0
- if iscmp[n.Op] && t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
- // comparison is okay as long as one side is
- // assignable to the other. convert so they have
- // the same type.
- //
- // the only conversion that isn't a no-op is concrete == interface.
- // in that case, check comparability of the concrete type.
- // The conversion allocates, so only do it if the concrete type is huge.
- if r.Type.Etype != TBLANK {
- aop = assignop(l.Type, r.Type, nil)
- if aop != 0 {
- if Isinter(r.Type) && !Isinter(l.Type) && algtype1(l.Type, nil) == ANOEQ {
- Yyerror("invalid operation: %v (operator %v not defined on %s)", Nconv(n, 0), Oconv(int(op), 0), typekind(l.Type))
- goto error
- }
-
- dowidth(l.Type)
- if Isinter(r.Type) == Isinter(l.Type) || l.Type.Width >= 1<<16 {
- l = Nod(aop, l, nil)
- l.Type = r.Type
- l.Typecheck = 1
- n.Left = l
- }
-
- t = r.Type
- goto converted
- }
- }
-
- if l.Type.Etype != TBLANK {
- aop = assignop(r.Type, l.Type, nil)
- if aop != 0 {
- if Isinter(l.Type) && !Isinter(r.Type) && algtype1(r.Type, nil) == ANOEQ {
- Yyerror("invalid operation: %v (operator %v not defined on %s)", Nconv(n, 0), Oconv(int(op), 0), typekind(r.Type))
- goto error
- }
-
- dowidth(r.Type)
- if Isinter(r.Type) == Isinter(l.Type) || r.Type.Width >= 1<<16 {
- r = Nod(aop, r, nil)
- r.Type = l.Type
- r.Typecheck = 1
- n.Right = r
- }
-
- t = l.Type
- }
- }
-
- converted:
- et = int(t.Etype)
- }
-
- if t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
- defaultlit2(&l, &r, 1)
- if n.Op == OASOP && n.Implicit != 0 {
- Yyerror("invalid operation: %v (non-numeric type %v)", Nconv(n, 0), Tconv(l.Type, 0))
- goto error
- }
-
- if Isinter(r.Type) == Isinter(l.Type) || aop == 0 {
- Yyerror("invalid operation: %v (mismatched types %v and %v)", Nconv(n, 0), Tconv(l.Type, 0), Tconv(r.Type, 0))
- goto error
- }
- }
-
- if !okfor[op][et] {
- Yyerror("invalid operation: %v (operator %v not defined on %s)", Nconv(n, 0), Oconv(int(op), 0), typekind(t))
- goto error
- }
-
- // okfor allows any array == array, map == map, func == func.
- // restrict to slice/map/func == nil and nil == slice/map/func.
- if Isfixedarray(l.Type) && algtype1(l.Type, nil) == ANOEQ {
- Yyerror("invalid operation: %v (%v cannot be compared)", Nconv(n, 0), Tconv(l.Type, 0))
- goto error
- }
-
- if Isslice(l.Type) && !isnil(l) && !isnil(r) {
- Yyerror("invalid operation: %v (slice can only be compared to nil)", Nconv(n, 0))
- goto error
- }
-
- if l.Type.Etype == TMAP && !isnil(l) && !isnil(r) {
- Yyerror("invalid operation: %v (map can only be compared to nil)", Nconv(n, 0))
- goto error
- }
-
- if l.Type.Etype == TFUNC && !isnil(l) && !isnil(r) {
- Yyerror("invalid operation: %v (func can only be compared to nil)", Nconv(n, 0))
- goto error
- }
-
- if l.Type.Etype == TSTRUCT && algtype1(l.Type, &badtype) == ANOEQ {
- Yyerror("invalid operation: %v (struct containing %v cannot be compared)", Nconv(n, 0), Tconv(badtype, 0))
- goto error
- }
-
- t = l.Type
- if iscmp[n.Op] {
- evconst(n)
- t = idealbool
- if n.Op != OLITERAL {
- defaultlit2(&l, &r, 1)
- n.Left = l
- n.Right = r
- }
- } else if n.Op == OANDAND || n.Op == OOROR {
- if l.Type == r.Type {
- t = l.Type
- } else if l.Type == idealbool {
- t = r.Type
- } else if r.Type == idealbool {
- t = l.Type
- }
- } else
- // non-comparison operators on ideal bools should make them lose their ideal-ness
- if t == idealbool {
- t = Types[TBOOL]
- }
-
- if et == TSTRING {
- if iscmp[n.Op] {
- n.Etype = n.Op
- n.Op = OCMPSTR
- } else if n.Op == OADD {
- // create OADDSTR node with list of strings in x + y + z + (w + v) + ...
- n.Op = OADDSTR
-
- if l.Op == OADDSTR {
- n.List = l.List
- } else {
- n.List = list1(l)
- }
- if r.Op == OADDSTR {
- n.List = concat(n.List, r.List)
- } else {
- n.List = list(n.List, r)
- }
- n.Left = nil
- n.Right = nil
- }
- }
-
- if et == TINTER {
- if l.Op == OLITERAL && l.Val.Ctype == CTNIL {
- // swap for back end
- n.Left = r
-
- n.Right = l
- } else if r.Op == OLITERAL && r.Val.Ctype == CTNIL {
- } else // leave alone for back end
- if Isinter(r.Type) == Isinter(l.Type) {
- n.Etype = n.Op
- n.Op = OCMPIFACE
- }
- }
-
- if (op == ODIV || op == OMOD) && Isconst(r, CTINT) {
- if mpcmpfixc(r.Val.U.Xval, 0) == 0 {
- Yyerror("division by zero")
- goto error
- }
- }
-
- n.Type = t
- goto ret
-
-doconv:
- ok |= Erv
- saveorignode(n)
- typecheck(&n.Left, Erv|top&(Eindir|Eiota))
- convlit1(&n.Left, n.Type, true)
- t = n.Left.Type
- if t == nil || n.Type == nil {
- goto error
- }
- n.Op = uint8(convertop(t, n.Type, &why))
- if (n.Op) == 0 {
- if n.Diag == 0 && n.Type.Broke == 0 {
- Yyerror("cannot convert %v to type %v%s", Nconv(n.Left, obj.FmtLong), Tconv(n.Type, 0), why)
- n.Diag = 1
- }
-
- n.Op = OCONV
- }
-
- switch n.Op {
- case OCONVNOP:
- if n.Left.Op == OLITERAL && n.Type != Types[TBOOL] {
- r := Nod(OXXX, nil, nil)
- n.Op = OCONV
- n.Orig = r
- *r = *n
- n.Op = OLITERAL
- n.Val = n.Left.Val
- }
-
- // do not use stringtoarraylit.
- // generated code and compiler memory footprint is better without it.
- case OSTRARRAYBYTE:
- break
-
- case OSTRARRAYRUNE:
- if n.Left.Op == OLITERAL {
- stringtoarraylit(&n)
- }
- }
-
- goto ret
-
-ret:
- t = n.Type
+ t := n.Type
if t != nil && t.Funarg == 0 && n.Op != OTYPE {
switch t.Etype {
case TFUNC, // might have TANY; wait until its called
@@ -2078,18 +2202,21 @@
evconst(n)
if n.Op == OTYPE && top&Etype == 0 {
Yyerror("type %v is not an expression", Tconv(n.Type, 0))
- goto error
+ n.Type = nil
+ return
}
if top&(Erv|Etype) == Etype && n.Op != OTYPE {
Yyerror("%v is not a type", Nconv(n, 0))
- goto error
+ n.Type = nil
+ return
}
// TODO(rsc): simplify
if (top&(Ecall|Erv|Etype) != 0) && top&Etop == 0 && ok&(Erv|Etype|Ecall) == 0 {
Yyerror("%v used as value", Nconv(n, 0))
- goto error
+ n.Type = nil
+ return
}
if (top&Etop != 0) && top&(Ecall|Erv|Etype) == 0 && ok&Etop == 0 {
@@ -2098,24 +2225,14 @@
n.Diag = 1
}
- goto error
+ n.Type = nil
+ return
}
/* TODO
if(n->type == T)
fatal("typecheck nil type");
*/
- goto out
-
-badcall1:
- Yyerror("invalid argument %v for %v", Nconv(n.Left, obj.FmtLong), Oconv(int(n.Op), 0))
- goto error
-
-error:
- n.Type = nil
-
-out:
- *np = n
}
func checksliceindex(l *Node, r *Node, tp *Type) int {
@@ -2840,35 +2957,35 @@
}
func typecheckcomplit(np **Node) {
- var nerr int
- var l *Node
- var norig *Node
- var r *Node
- var t *Type
-
n := *np
lno := lineno
+ defer func() {
+ lineno = lno
+ *np = n
+ }()
if n.Right == nil {
if n.List != nil {
setlineno(n.List.N)
}
Yyerror("missing type in composite literal")
- goto error
+ n.Type = nil
+ return
}
// Save original node (including n->right)
- norig = Nod(int(n.Op), nil, nil)
+ norig := Nod(int(n.Op), nil, nil)
*norig = *n
setlineno(n.Right)
- l = typecheck(&n.Right, Etype|Ecomplit) /* sic */
- t = l.Type
+ l := typecheck(&n.Right, Etype|Ecomplit) /* sic */
+ t := l.Type
if t == nil {
- goto error
+ n.Type = nil
+ return
}
- nerr = nerrors
+ nerr := nerrors
n.Type = t
if Isptr[t.Etype] {
@@ -2876,18 +2993,21 @@
// except when using the &T syntax, which sets implicit on the OIND.
if n.Right.Implicit == 0 {
Yyerror("invalid pointer type %v for composite literal (use &%v instead)", Tconv(t, 0), Tconv(t.Type, 0))
- goto error
+ n.Type = nil
+ return
}
// Also, the underlying type must be a struct, map, slice, or array.
if !iscomptype(t) {
Yyerror("invalid pointer type %v for composite literal", Tconv(t, 0))
- goto error
+ n.Type = nil
+ return
}
t = t.Type
}
+ var r *Node
switch t.Etype {
default:
Yyerror("invalid type for composite literal: %v", Tconv(t, 0))
@@ -3075,7 +3195,8 @@
}
if nerr != nerrors {
- goto error
+ n.Type = nil
+ return
}
n.Orig = norig
@@ -3088,14 +3209,7 @@
}
n.Orig = norig
- *np = n
- lineno = lno
return
-
-error:
- n.Type = nil
- *np = n
- lineno = lno
}
/*
diff --git a/src/cmd/internal/gc/walk.go b/src/cmd/internal/gc/walk.go
index ed46809..0992c18 100644
--- a/src/cmd/internal/gc/walk.go
+++ b/src/cmd/internal/gc/walk.go
@@ -3235,9 +3235,6 @@
// Checking src[lb:hb:cb] or src[lb:hb].
// if chk0 || chk1 || chk2 { panicslice() }
- var chk0 *Node // cap(src) < cb
- var chk1 *Node // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb]
- var chk2 *Node // hb < lb
// All comparisons are unsigned to avoid testing < 0.
bt := Types[Simtype[TUINT]]
@@ -3254,6 +3251,7 @@
bound = cheapexpr(conv(bound, bt), init)
+ var chk0 *Node // cap(src) < cb
if cb != nil {
cb = cheapexpr(conv(cb, bt), init)
if bounded == 0 {
@@ -3264,6 +3262,7 @@
Fatal("slice3 with cb == N") // rejected by parser
}
+ var chk1 *Node // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb]
if hb != nil {
hb = cheapexpr(conv(hb, bt), init)
if bounded == 0 {
@@ -3285,6 +3284,7 @@
hb = cheapexpr(conv(hb, bt), init)
}
+ var chk2 *Node // hb < lb
if lb != nil {
lb = cheapexpr(conv(lb, bt), init)
if bounded == 0 {
@@ -3432,14 +3432,6 @@
r = n.Left
}
- var call *Node
- var a *Node
- var cmpl *Node
- var cmpr *Node
- var andor int
- var expr *Node
- var needsize int
- var t *Type
if l != nil {
x := temp(r.Type)
ok := temp(Types[TBOOL])
@@ -3464,12 +3456,13 @@
r = Nod(OOROR, Nod(ONOT, ok, nil), Nod(ONE, x, r))
}
*init = list(*init, expr)
- goto ret
+ finishcompare(np, n, r, init)
+ return
}
// Must be comparison of array or struct.
// Otherwise back end handles it.
- t = n.Left.Type
+ t := n.Left.Type
switch t.Etype {
default:
@@ -3484,11 +3477,11 @@
break
}
- cmpl = n.Left
+ cmpl := n.Left
for cmpl != nil && cmpl.Op == OCONVNOP {
cmpl = cmpl.Left
}
- cmpr = n.Right
+ cmpr := n.Right
for cmpr != nil && cmpr.Op == OCONVNOP {
cmpr = cmpr.Left
}
@@ -3498,7 +3491,7 @@
}
l = temp(Ptrto(t))
- a = Nod(OAS, l, Nod(OADDR, cmpl, nil))
+ a := Nod(OAS, l, Nod(OADDR, cmpl, nil))
a.Right.Etype = 1 // addr does not escape
typecheck(&a, Etop)
*init = list(*init, a)
@@ -3509,12 +3502,12 @@
typecheck(&a, Etop)
*init = list(*init, a)
- expr = nil
- andor = OANDAND
+ andor := OANDAND
if n.Op == ONE {
andor = OOROR
}
+ var expr *Node
if t.Etype == TARRAY && t.Bound <= 4 && issimple[t.Type.Etype] {
// Four or fewer elements of a basic type.
// Unroll comparisons.
@@ -3534,8 +3527,8 @@
if expr == nil {
expr = Nodbool(n.Op == OEQ)
}
- r = expr
- goto ret
+ finishcompare(np, n, expr, init)
+ return
}
if t.Etype == TSTRUCT && countfield(t) <= 4 {
@@ -3560,12 +3553,13 @@
if expr == nil {
expr = Nodbool(n.Op == OEQ)
}
- r = expr
- goto ret
+ finishcompare(np, n, expr, init)
+ return
}
// Chose not to inline. Call equality function directly.
- call = Nod(OCALL, eqfor(t, &needsize), nil)
+ var needsize int
+ call := Nod(OCALL, eqfor(t, &needsize), nil)
call.List = list(call.List, l)
call.List = list(call.List, r)
@@ -3576,19 +3570,23 @@
if n.Op != OEQ {
r = Nod(ONOT, r, nil)
}
- goto ret
-ret:
- typecheck(&r, Erv)
- walkexpr(&r, init)
+ finishcompare(np, n, r, init)
+ return
+}
+
+func finishcompare(np **Node, n, r *Node, init **NodeList) {
+ // Using np here to avoid passing &r to typecheck.
+ *np = r
+ typecheck(np, Erv)
+ walkexpr(np, init)
+ r = *np
if r.Type != n.Type {
r = Nod(OCONVNOP, r, nil)
r.Type = n.Type
r.Typecheck = 1
+ *np = r
}
-
- *np = r
- return
}
func samecheap(a *Node, b *Node) bool {