aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2011-06-20 14:06:00 -0400
committerRuss Cox <rsc@golang.org>2011-06-20 14:06:00 -0400
commite0a617496e52b7e1b71ca95ff5b10e4945267e0e (patch)
tree45e4163437503fc078990b7553d406bc02e398ff
parentda7b96f714c3b5047a1af6903fa2d73f29693b00 (diff)
downloadgo-e0a617496e52b7e1b71ca95ff5b10e4945267e0e.tar.gz
go-e0a617496e52b7e1b71ca95ff5b10e4945267e0e.zip
test: test of goto restrictions
R=gri, iant, bradfitz, fvbommel, r CC=golang-dev https://golang.org/cl/4652041
-rwxr-xr-xtest/errchk16
-rw-r--r--test/goto.go535
2 files changed, 551 insertions, 0 deletions
diff --git a/test/errchk b/test/errchk
index fbb021ce41..e89d759508 100755
--- a/test/errchk
+++ b/test/errchk
@@ -81,6 +81,19 @@ sub chk {
next;
}
$regexp = $1;
+
+ # Turn relative line number in message into absolute line number.
+ if($regexp =~ /LINE(([+-])([0-9]+))?/) {
+ my $n = $line;
+ if(defined($1)) {
+ if($2 eq "+") {
+ $n += int($3);
+ } else {
+ $n -= int($3);
+ }
+ }
+ $regexp = "$`$file:$n$'";
+ }
@errmsg = grep { /$file:$line[:[]/ } @out;
@out = grep { !/$file:$line[:[]/ } @out;
@@ -93,6 +106,9 @@ sub chk {
if(@match == 0) {
bug();
print STDERR "errchk: $file:$line: error message does not match '$regexp'\n";
+ foreach my $l (@errmsg) {
+ print STDERR "> $l";
+ }
next;
}
}
diff --git a/test/goto.go b/test/goto.go
new file mode 100644
index 0000000000..0a50938dcf
--- /dev/null
+++ b/test/goto.go
@@ -0,0 +1,535 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 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.
+
+// Each test is in a separate function just so that if the
+// compiler stops processing after one error, we don't
+// lose other ones.
+
+package main
+
+var (
+ i, n int
+ x []int
+ c chan int
+ m map[int]int
+ s string
+)
+
+// goto after declaration okay
+func _() {
+ x := 1
+ goto L
+L:
+ _ = x
+}
+
+// goto before declaration okay
+func _() {
+ goto L
+L:
+ x := 1
+ _ = x
+}
+
+// goto across declaration not okay
+func _() {
+ goto L // ERROR "goto L jumps over declaration of x at LINE+1"
+ x := 1
+ _ = x
+L:
+}
+
+// goto across declaration in inner scope okay
+func _() {
+ goto L
+ {
+ x := 1
+ _ = x
+ }
+L:
+}
+
+// goto across declaration after inner scope not okay
+func _() {
+ goto L // ERROR "goto L jumps over declaration of x at LINE+5"
+ {
+ x := 1
+ _ = x
+ }
+ x := 1
+ _ = x
+L:
+}
+
+// goto across declaration in reverse okay
+func _() {
+L:
+ x := 1
+ _ = x
+ goto L
+}
+
+// error shows first offending variable
+func _() {
+ goto L // ERROR "goto L jumps over declaration of x at LINE+1"
+ x := 1
+ _ = x
+ y := 1
+ _ = y
+L:
+}
+
+// goto not okay even if code path is dead
+func _() {
+ goto L // ERROR "goto L jumps over declaration of x at LINE+1"
+ x := 1
+ _ = x
+ y := 1
+ _ = y
+ return
+L:
+}
+
+// goto into outer block okay
+func _() {
+ {
+ goto L
+ }
+L:
+}
+
+// goto backward into outer block okay
+func _() {
+L:
+ {
+ goto L
+ }
+}
+
+// goto into inner block not okay
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ {
+ L:
+ }
+}
+
+// goto backward into inner block still not okay
+func _() {
+ {
+ L:
+ }
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+}
+
+// error shows first (outermost) offending block
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ {
+ {
+ {
+ L:
+ }
+ }
+ }
+}
+
+// error prefers block diagnostic over declaration diagnostic
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+3"
+ x := 1
+ _ = x
+ {
+ L:
+ }
+}
+
+// many kinds of blocks, all invalid to jump into or among,
+// but valid to jump out of
+
+// if
+
+func _() {
+L:
+ if true {
+ goto L
+ }
+}
+
+func _() {
+L:
+ if true {
+ goto L
+ } else {
+ }
+}
+
+func _() {
+L:
+ if false {
+ } else {
+ goto L
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ if true {
+ L:
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ if true {
+ L:
+ } else {
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ if true {
+ } else {
+ L:
+ }
+}
+
+func _() {
+ if false {
+ L:
+ } else {
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+ }
+}
+
+func _() {
+ if true {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ } else {
+ L:
+ }
+}
+
+func _() {
+ if true {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ } else if false {
+ L:
+ }
+}
+
+func _() {
+ if true {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ } else if false {
+ L:
+ } else {
+ }
+}
+
+func _() {
+ // This one is tricky. There is an implicit scope
+ // starting at the second if statement, and it contains
+ // the final else, so the outermost offending scope
+ // really is LINE+1 (like in the previous test),
+ // even though it looks like it might be LINE+3 instead.
+ if true {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ } else if false {
+ } else {
+ L:
+ }
+}
+
+/* Want to enable these tests but gofmt mangles them. Issue 1972.
+
+func _() {
+ // This one is okay, because the else is in the
+ // implicit whole-if block and has no inner block
+ // (no { }) around it.
+ if true {
+ goto L
+ } else
+ L:
+}
+
+func _() {
+ // Still not okay.
+ if true {
+ L:
+ } else
+ goto L //// ERROR "goto L jumps into block starting at LINE-3"
+}
+
+*/
+
+// for
+
+func _() {
+ for {
+ goto L
+ }
+L:
+}
+
+func _() {
+ for {
+ goto L
+ L:
+ }
+}
+
+func _() {
+ for {
+ L:
+ }
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+}
+
+func _() {
+ for {
+ goto L
+ L1:
+ }
+L:
+ goto L1 // ERROR "goto L1 jumps into block starting at LINE-5"
+}
+
+func _() {
+ for i < n {
+ L:
+ }
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+}
+
+func _() {
+ for i = 0; i < n; i++ {
+ L:
+ }
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+}
+
+func _() {
+ for i = range x {
+ L:
+ }
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+}
+
+func _() {
+ for i = range c {
+ L:
+ }
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+}
+
+func _() {
+ for i = range m {
+ L:
+ }
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+}
+
+func _() {
+ for i = range s {
+ L:
+ }
+ goto L // ERROR "goto L jumps into block starting at LINE-3"
+}
+
+// switch
+
+func _() {
+L:
+ switch i {
+ case 0:
+ goto L
+ }
+}
+
+func _() {
+L:
+ switch i {
+ case 0:
+
+ default:
+ goto L
+ }
+}
+
+func _() {
+ switch i {
+ case 0:
+
+ default:
+ L:
+ goto L
+ }
+}
+
+func _() {
+ switch i {
+ case 0:
+
+ default:
+ goto L
+ L:
+ }
+}
+
+func _() {
+ switch i {
+ case 0:
+ goto L
+ L:
+ ;
+ default:
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ switch i {
+ case 0:
+ L:
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ switch i {
+ case 0:
+ L:
+ ;
+ default:
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ switch i {
+ case 0:
+ default:
+ L:
+ }
+}
+
+func _() {
+ switch i {
+ default:
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ case 0:
+ L:
+ }
+}
+
+func _() {
+ switch i {
+ case 0:
+ L:
+ ;
+ default:
+ goto L // ERROR "goto L jumps into block starting at LINE-4"
+ }
+}
+
+// select
+// different from switch. the statement has no implicit block around it.
+
+func _() {
+L:
+ select {
+ case <-c:
+ goto L
+ }
+}
+
+func _() {
+L:
+ select {
+ case c <- 1:
+
+ default:
+ goto L
+ }
+}
+
+func _() {
+ select {
+ case <-c:
+
+ default:
+ L:
+ goto L
+ }
+}
+
+func _() {
+ select {
+ case c <- 1:
+
+ default:
+ goto L
+ L:
+ }
+}
+
+func _() {
+ select {
+ case <-c:
+ goto L
+ L:
+ ;
+ default:
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+2"
+ select {
+ case c <- 1:
+ L:
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+2"
+ select {
+ case c <- 1:
+ L:
+ ;
+ default:
+ }
+}
+
+func _() {
+ goto L // ERROR "goto L jumps into block starting at LINE+3"
+ select {
+ case <-c:
+ default:
+ L:
+ }
+}
+
+func _() {
+ select {
+ default:
+ goto L // ERROR "goto L jumps into block starting at LINE+1"
+ case <-c:
+ L:
+ }
+}
+
+func _() {
+ select {
+ case <-c:
+ L:
+ ;
+ default:
+ goto L // ERROR "goto L jumps into block starting at LINE-4"
+ }
+}