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