mirror of
https://github.com/golang/go
synced 2024-11-25 12:07:56 -07:00
break and continue fixes
labeled break/continue was using first loop with any label, not first loop with the right label. R=ken OCL=32453 CL=32458
This commit is contained in:
parent
75e0569b99
commit
2946069e3f
@ -97,6 +97,8 @@ zaddr(Biobuf *b, Addr *a, int s)
|
|||||||
switch(a->type) {
|
switch(a->type) {
|
||||||
|
|
||||||
case D_BRANCH:
|
case D_BRANCH:
|
||||||
|
if(a->branch == nil)
|
||||||
|
fatal("unpatched branch");
|
||||||
a->offset = a->branch->loc;
|
a->offset = a->branch->loc;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -97,6 +97,8 @@ zaddr(Biobuf *b, Addr *a, int s)
|
|||||||
switch(a->type) {
|
switch(a->type) {
|
||||||
|
|
||||||
case D_BRANCH:
|
case D_BRANCH:
|
||||||
|
if(a->branch == nil)
|
||||||
|
fatal("unpatched branch");
|
||||||
a->offset = a->branch->loc;
|
a->offset = a->branch->loc;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -162,7 +162,14 @@ gen(Node *n)
|
|||||||
case OFALL:
|
case OFALL:
|
||||||
case OXCASE:
|
case OXCASE:
|
||||||
case OXFALL:
|
case OXFALL:
|
||||||
|
break;
|
||||||
|
|
||||||
case OEMPTY:
|
case OEMPTY:
|
||||||
|
// insert no-op so that
|
||||||
|
// L:; for { }
|
||||||
|
// does not treat L as a label for the loop.
|
||||||
|
if(labellist && labellist->label == p3)
|
||||||
|
gused(N);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OBLOCK:
|
case OBLOCK:
|
||||||
@ -181,9 +188,11 @@ gen(Node *n)
|
|||||||
case OBREAK:
|
case OBREAK:
|
||||||
if(n->left != N) {
|
if(n->left != N) {
|
||||||
for(lab=labellist; lab!=L; lab=lab->link) {
|
for(lab=labellist; lab!=L; lab=lab->link) {
|
||||||
if(lab->breakpc != P) {
|
if(lab->sym == n->left->sym) {
|
||||||
|
if(lab->breakpc == P)
|
||||||
|
yyerror("invalid break label %S", n->left->sym);
|
||||||
gjmp(lab->breakpc);
|
gjmp(lab->breakpc);
|
||||||
break;
|
goto donebreak;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(lab == L)
|
if(lab == L)
|
||||||
@ -195,26 +204,30 @@ gen(Node *n)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gjmp(breakpc);
|
gjmp(breakpc);
|
||||||
|
donebreak:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OCONTINUE:
|
case OCONTINUE:
|
||||||
if(n->left != N) {
|
if(n->left != N) {
|
||||||
for(lab=labellist; lab!=L; lab=lab->link) {
|
for(lab=labellist; lab!=L; lab=lab->link) {
|
||||||
if(lab->continpc != P) {
|
if(lab->sym == n->left->sym) {
|
||||||
|
if(lab->continpc == P)
|
||||||
|
yyerror("invalid continue label %S", n->left->sym);
|
||||||
gjmp(lab->continpc);
|
gjmp(lab->continpc);
|
||||||
break;
|
goto donecont;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(lab == L)
|
if(lab == L)
|
||||||
yyerror("break label not defined: %S", n->left->sym);
|
yyerror("continue label not defined: %S", n->left->sym);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(continpc == P) {
|
if(continpc == P) {
|
||||||
yyerror("gen: continue is not in a loop");
|
yyerror("continue is not in a loop");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gjmp(continpc);
|
gjmp(continpc);
|
||||||
|
donecont:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OFOR:
|
case OFOR:
|
||||||
@ -224,15 +237,11 @@ gen(Node *n)
|
|||||||
scontin = continpc;
|
scontin = continpc;
|
||||||
continpc = pc;
|
continpc = pc;
|
||||||
|
|
||||||
// define break and cotinue labels
|
// define break and continue labels
|
||||||
for(lab=labellist; lab!=L; lab=lab->link) {
|
if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL) {
|
||||||
if(lab->label != p3)
|
|
||||||
break;
|
|
||||||
if(lab->op == OLABEL) {
|
|
||||||
lab->breakpc = breakpc;
|
lab->breakpc = breakpc;
|
||||||
lab->continpc = continpc;
|
lab->continpc = continpc;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gen(n->nincr); // contin: incr
|
gen(n->nincr); // contin: incr
|
||||||
patch(p1, pc); // test:
|
patch(p1, pc); // test:
|
||||||
@ -268,13 +277,8 @@ gen(Node *n)
|
|||||||
breakpc = gjmp(P); // break: goto done
|
breakpc = gjmp(P); // break: goto done
|
||||||
|
|
||||||
// define break label
|
// define break label
|
||||||
for(lab=labellist; lab!=L; lab=lab->link) {
|
if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL)
|
||||||
if(lab->label != p3)
|
|
||||||
break;
|
|
||||||
if(lab->op == OLABEL) {
|
|
||||||
lab->breakpc = breakpc;
|
lab->breakpc = breakpc;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
patch(p1, pc); // test:
|
patch(p1, pc); // test:
|
||||||
genlist(n->nbody); // switch(test) body
|
genlist(n->nbody); // switch(test) body
|
||||||
@ -288,13 +292,8 @@ gen(Node *n)
|
|||||||
breakpc = gjmp(P); // break: goto done
|
breakpc = gjmp(P); // break: goto done
|
||||||
|
|
||||||
// define break label
|
// define break label
|
||||||
for(lab=labellist; lab!=L; lab=lab->link) {
|
if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL)
|
||||||
if(lab->label != p3)
|
|
||||||
break;
|
|
||||||
if(lab->op == OLABEL) {
|
|
||||||
lab->breakpc = breakpc;
|
lab->breakpc = breakpc;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
patch(p1, pc); // test:
|
patch(p1, pc); // test:
|
||||||
genlist(n->nbody); // select() body
|
genlist(n->nbody); // select() body
|
||||||
|
27
test/fixedbugs/bug178.go
Normal file
27
test/fixedbugs/bug178.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L:
|
||||||
|
for i := 0; i < 1; i++ {
|
||||||
|
L1:
|
||||||
|
for {
|
||||||
|
break L;
|
||||||
|
}
|
||||||
|
panic("BUG: not reached - break");
|
||||||
|
}
|
||||||
|
|
||||||
|
L2:
|
||||||
|
for i := 0; i < 1; i++ {
|
||||||
|
L3:
|
||||||
|
for {
|
||||||
|
continue L2;
|
||||||
|
}
|
||||||
|
panic("BUG: not reached - continue");
|
||||||
|
}
|
||||||
|
}
|
24
test/fixedbugs/bug179.go
Normal file
24
test/fixedbugs/bug179.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// errchk $G -e $D/$F.go
|
||||||
|
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
L:
|
||||||
|
for {
|
||||||
|
for {
|
||||||
|
break L2; // ERROR "L2"
|
||||||
|
continue L2; // ERROR "L2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
L1:
|
||||||
|
x := 1;
|
||||||
|
for {
|
||||||
|
break L1; // ERROR "L1"
|
||||||
|
continue L1; // ERROR "L1"
|
||||||
|
}
|
||||||
|
}
|
@ -88,9 +88,6 @@ panic PC=xxx
|
|||||||
=========== bugs/bug132.go
|
=========== bugs/bug132.go
|
||||||
BUG: compilation succeeds incorrectly
|
BUG: compilation succeeds incorrectly
|
||||||
|
|
||||||
=========== bugs/bug136.go
|
|
||||||
BUG: should not compile
|
|
||||||
|
|
||||||
=========== bugs/bug159.go
|
=========== bugs/bug159.go
|
||||||
abc: expected 4 5 6 got 4 4 -4
|
abc: expected 4 5 6 got 4 4 -4
|
||||||
BUG: bug159
|
BUG: bug159
|
||||||
@ -227,6 +224,9 @@ fixedbugs/bug133.dir/bug2.go:11: undefined: bug0.T field i
|
|||||||
fixedbugs/bug133.dir/bug2.go:11: illegal types for operand: RETURN
|
fixedbugs/bug133.dir/bug2.go:11: illegal types for operand: RETURN
|
||||||
int
|
int
|
||||||
|
|
||||||
|
=========== fixedbugs/bug136.go
|
||||||
|
fixedbugs/bug136.go:9: invalid break label L
|
||||||
|
|
||||||
=========== fixedbugs/bug148.go
|
=========== fixedbugs/bug148.go
|
||||||
2 3
|
2 3
|
||||||
interface is main.T, not main.T·bug148·1
|
interface is main.T, not main.T·bug148·1
|
||||||
|
Loading…
Reference in New Issue
Block a user