diff options
Diffstat (limited to 'test/goto.go')
-rw-r--r-- | test/goto.go | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/test/goto.go b/test/goto.go new file mode 100644 index 0000000..d660c9c --- /dev/null +++ b/test/goto.go @@ -0,0 +1,538 @@ +// errorcheck + +// 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. + +// Verify goto semantics. +// Does not compile. +// +// 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|goto jumps over declaration" + x := 1 // GCCGO_ERROR "defined here" + _ = 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|goto jumps over declaration" + { + x := 1 + _ = x + } + x := 1 // GCCGO_ERROR "defined here" + _ = 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 y at LINE+3|goto jumps over declaration" + x := 1 // GCCGO_ERROR "defined here" + _ = x + y := 1 + _ = y +L: +} + +// goto not okay even if code path is dead +func _() { + goto L // ERROR "goto L jumps over declaration of y at LINE+3|goto jumps over declaration" + x := 1 // GCCGO_ERROR "defined here" + _ = 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|goto jumps into block" + { // GCCGO_ERROR "block starts here" + L: + } +} + +// goto backward into inner block still not okay +func _() { + { // GCCGO_ERROR "block starts here" + L: + } + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +// error shows first (outermost) offending block +func _() { + goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block" + { + { + { // GCCGO_ERROR "block starts here" + L: + } + } + } +} + +// error prefers block diagnostic over declaration diagnostic +func _() { + goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block" + x := 1 + _ = x + { // GCCGO_ERROR "block starts here" + 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|goto jumps into block" + if true { // GCCGO_ERROR "block starts here" + L: + } +} + +func _() { + goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" + if true { // GCCGO_ERROR "block starts here" + L: + } else { + } +} + +func _() { + goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block" + if true { + } else { // GCCGO_ERROR "block starts here" + L: + } +} + +func _() { + if false { // GCCGO_ERROR "block starts here" + L: + } else { + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" + } +} + +func _() { + if true { + goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" + } else { // GCCGO_ERROR "block starts here" + L: + } +} + +func _() { + if true { + goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" + } else if false { // GCCGO_ERROR "block starts here" + L: + } +} + +func _() { + if true { + goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" + } else if false { // GCCGO_ERROR "block starts here" + 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+2|goto jumps into block" + } else if false { + } else { // GCCGO_ERROR "block starts here" + 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 { //// GCCGO_ERROR "block starts here" + L: + } else + goto L //// ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +*/ + +// for + +func _() { + for { + goto L + } +L: +} + +func _() { + for { + goto L + L: + } +} + +func _() { + for { // GCCGO_ERROR "block starts here" + L: + } + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +func _() { + for { // GCCGO_ERROR "block starts here" + goto L + L1: + } +L: + goto L1 // ERROR "goto L1 jumps into block starting at LINE-5|goto jumps into block" +} + +func _() { + for i < n { // GCCGO_ERROR "block starts here" + L: + } + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +func _() { + for i = 0; i < n; i++ { // GCCGO_ERROR "block starts here" + L: + } + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +func _() { + for i = range x { // GCCGO_ERROR "block starts here" + L: + } + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +func _() { + for i = range c { // GCCGO_ERROR "block starts here" + L: + } + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +func _() { + for i = range m { // GCCGO_ERROR "block starts here" + L: + } + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +func _() { + for i = range s { // GCCGO_ERROR "block starts here" + L: + } + goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block" +} + +// 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+2|goto jumps into block" + switch i { + case 0: + L: // GCCGO_ERROR "block starts here" + } +} + +func _() { + goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block" + switch i { + case 0: + L: // GCCGO_ERROR "block starts here" + ; + default: + } +} + +func _() { + goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block" + switch i { + case 0: + default: + L: // GCCGO_ERROR "block starts here" + } +} + +func _() { + switch i { + default: + goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" + case 0: + L: // GCCGO_ERROR "block starts here" + } +} + +func _() { + switch i { + case 0: + L: // GCCGO_ERROR "block starts here" + ; + default: + goto L // ERROR "goto L jumps into block starting at LINE-4|goto jumps into block" + } +} + +// 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|goto jumps into block" + select { + case c <- 1: + L: // GCCGO_ERROR "block starts here" + } +} + +func _() { + goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block" + select { + case c <- 1: + L: // GCCGO_ERROR "block starts here" + ; + default: + } +} + +func _() { + goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block" + select { + case <-c: + default: + L: // GCCGO_ERROR "block starts here" + } +} + +func _() { + select { + default: + goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" + case <-c: + L: // GCCGO_ERROR "block starts here" + } +} + +func _() { + select { + case <-c: + L: // GCCGO_ERROR "block starts here" + ; + default: + goto L // ERROR "goto L jumps into block starting at LINE-4|goto jumps into block" + } +} |