mirror of
https://github.com/golang/go
synced 2024-11-22 00:14:42 -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) {
|
||||
|
||||
case D_BRANCH:
|
||||
if(a->branch == nil)
|
||||
fatal("unpatched branch");
|
||||
a->offset = a->branch->loc;
|
||||
|
||||
default:
|
||||
|
@ -97,6 +97,8 @@ zaddr(Biobuf *b, Addr *a, int s)
|
||||
switch(a->type) {
|
||||
|
||||
case D_BRANCH:
|
||||
if(a->branch == nil)
|
||||
fatal("unpatched branch");
|
||||
a->offset = a->branch->loc;
|
||||
|
||||
default:
|
||||
|
@ -162,7 +162,14 @@ gen(Node *n)
|
||||
case OFALL:
|
||||
case OXCASE:
|
||||
case OXFALL:
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
case OBLOCK:
|
||||
@ -181,9 +188,11 @@ gen(Node *n)
|
||||
case OBREAK:
|
||||
if(n->left != N) {
|
||||
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);
|
||||
break;
|
||||
goto donebreak;
|
||||
}
|
||||
}
|
||||
if(lab == L)
|
||||
@ -195,26 +204,30 @@ gen(Node *n)
|
||||
break;
|
||||
}
|
||||
gjmp(breakpc);
|
||||
donebreak:
|
||||
break;
|
||||
|
||||
case OCONTINUE:
|
||||
if(n->left != N) {
|
||||
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);
|
||||
break;
|
||||
goto donecont;
|
||||
}
|
||||
}
|
||||
if(lab == L)
|
||||
yyerror("break label not defined: %S", n->left->sym);
|
||||
yyerror("continue label not defined: %S", n->left->sym);
|
||||
break;
|
||||
}
|
||||
|
||||
if(continpc == P) {
|
||||
yyerror("gen: continue is not in a loop");
|
||||
yyerror("continue is not in a loop");
|
||||
break;
|
||||
}
|
||||
gjmp(continpc);
|
||||
donecont:
|
||||
break;
|
||||
|
||||
case OFOR:
|
||||
@ -224,15 +237,11 @@ gen(Node *n)
|
||||
scontin = continpc;
|
||||
continpc = pc;
|
||||
|
||||
// define break and cotinue labels
|
||||
for(lab=labellist; lab!=L; lab=lab->link) {
|
||||
if(lab->label != p3)
|
||||
break;
|
||||
if(lab->op == OLABEL) {
|
||||
// define break and continue labels
|
||||
if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL) {
|
||||
lab->breakpc = breakpc;
|
||||
lab->continpc = continpc;
|
||||
}
|
||||
}
|
||||
|
||||
gen(n->nincr); // contin: incr
|
||||
patch(p1, pc); // test:
|
||||
@ -268,13 +277,8 @@ gen(Node *n)
|
||||
breakpc = gjmp(P); // break: goto done
|
||||
|
||||
// define break label
|
||||
for(lab=labellist; lab!=L; lab=lab->link) {
|
||||
if(lab->label != p3)
|
||||
break;
|
||||
if(lab->op == OLABEL) {
|
||||
if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL)
|
||||
lab->breakpc = breakpc;
|
||||
}
|
||||
}
|
||||
|
||||
patch(p1, pc); // test:
|
||||
genlist(n->nbody); // switch(test) body
|
||||
@ -288,13 +292,8 @@ gen(Node *n)
|
||||
breakpc = gjmp(P); // break: goto done
|
||||
|
||||
// define break label
|
||||
for(lab=labellist; lab!=L; lab=lab->link) {
|
||||
if(lab->label != p3)
|
||||
break;
|
||||
if(lab->op == OLABEL) {
|
||||
if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL)
|
||||
lab->breakpc = breakpc;
|
||||
}
|
||||
}
|
||||
|
||||
patch(p1, pc); // test:
|
||||
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
|
||||
BUG: compilation succeeds incorrectly
|
||||
|
||||
=========== bugs/bug136.go
|
||||
BUG: should not compile
|
||||
|
||||
=========== bugs/bug159.go
|
||||
abc: expected 4 5 6 got 4 4 -4
|
||||
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
|
||||
int
|
||||
|
||||
=========== fixedbugs/bug136.go
|
||||
fixedbugs/bug136.go:9: invalid break label L
|
||||
|
||||
=========== fixedbugs/bug148.go
|
||||
2 3
|
||||
interface is main.T, not main.T·bug148·1
|
||||
|
Loading…
Reference in New Issue
Block a user