1
0
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:
Russ Cox 2009-07-29 14:49:01 -07:00
parent 75e0569b99
commit 2946069e3f
7 changed files with 85 additions and 31 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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
View 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
View 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"
}
}

View File

@ -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