...
Run Format

Source file test/goto.go

Documentation: test

  // 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 x at LINE+1|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 x at LINE+1|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+1|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+1|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+1|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+1|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+1|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+1|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"
  	}
  }
  

View as plain text