summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-07-29 14:49:01 -0700
committerRuss Cox <rsc@golang.org>2009-07-29 14:49:01 -0700
commit475f98271e13aa68604ad6dcb90b32067667cb9d (patch)
tree277506caa406741238a95a9f03a957216fa60376
parent9f88ec206af2f2014e9602470a328c5c0618df8a (diff)
downloadgolang-475f98271e13aa68604ad6dcb90b32067667cb9d.tar.gz
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
-rw-r--r--src/cmd/6g/gobj.c2
-rw-r--r--src/cmd/8g/gobj.c2
-rw-r--r--src/cmd/gc/gen.c55
-rw-r--r--test/fixedbugs/bug136.go (renamed from test/bugs/bug136.go)0
-rw-r--r--test/fixedbugs/bug178.go27
-rw-r--r--test/fixedbugs/bug179.go24
-rw-r--r--test/golden.out6
7 files changed, 85 insertions, 31 deletions
diff --git a/src/cmd/6g/gobj.c b/src/cmd/6g/gobj.c
index 1d7c07eba..6199d2f2f 100644
--- a/src/cmd/6g/gobj.c
+++ b/src/cmd/6g/gobj.c
@@ -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:
diff --git a/src/cmd/8g/gobj.c b/src/cmd/8g/gobj.c
index 96762375f..683c77d40 100644
--- a/src/cmd/8g/gobj.c
+++ b/src/cmd/8g/gobj.c
@@ -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:
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 1c05a0ba6..46373f8b8 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -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,14 +237,10 @@ 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) {
- lab->breakpc = breakpc;
- lab->continpc = continpc;
- }
+ // 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
@@ -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) {
- lab->breakpc = breakpc;
- }
- }
+ 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) {
- lab->breakpc = breakpc;
- }
- }
+ if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL)
+ lab->breakpc = breakpc;
patch(p1, pc); // test:
genlist(n->nbody); // select() body
diff --git a/test/bugs/bug136.go b/test/fixedbugs/bug136.go
index 5846c654b..5846c654b 100644
--- a/test/bugs/bug136.go
+++ b/test/fixedbugs/bug136.go
diff --git a/test/fixedbugs/bug178.go b/test/fixedbugs/bug178.go
new file mode 100644
index 000000000..4f586342b
--- /dev/null
+++ b/test/fixedbugs/bug178.go
@@ -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");
+ }
+}
diff --git a/test/fixedbugs/bug179.go b/test/fixedbugs/bug179.go
new file mode 100644
index 000000000..690b01265
--- /dev/null
+++ b/test/fixedbugs/bug179.go
@@ -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"
+ }
+}
diff --git a/test/golden.out b/test/golden.out
index be5f7482b..a92efaffe 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -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