|  | // 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" | 
|  | } | 
|  | } |