mirror of
				https://github.com/golang/go.git
				synced 2025-11-03 18:20:59 +00:00 
			
		
		
		
	Follow-up on https://go-review.googlesource.com/#/c/39998/ which dropped this information. The reported blocks are the innermost blocks containing a label jumped to from outside, not the outermost block as reported originally by cmd/compile. We could report the outermost block with a slighly more involved algorithm (need to track containing blocks for all unresolved forward gotos), but since gccgo also reports the innermost blocks, the current approach seems good enough. Change-Id: Ic0235b8fafe8d5f99dc9872b58e90e8d9e72c5db Reviewed-on: https://go-review.googlesource.com/40980 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Marvin Stenger <marvin.stenger94@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
		
			
				
	
	
		
			538 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			538 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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"
 | 
						|
	}
 | 
						|
}
 |