Source file test/goto.go

     1  // errorcheck
     2  
     3  // Copyright 2011 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Verify goto semantics.
     8  // Does not compile.
     9  //
    10  // Each test is in a separate function just so that if the
    11  // compiler stops processing after one error, we don't
    12  // lose other ones.
    13  
    14  package main
    15  
    16  var (
    17  	i, n int
    18  	x    []int
    19  	c    chan int
    20  	m    map[int]int
    21  	s    string
    22  )
    23  
    24  // goto after declaration okay
    25  func _() {
    26  	x := 1
    27  	goto L
    28  L:
    29  	_ = x
    30  }
    31  
    32  // goto before declaration okay
    33  func _() {
    34  	goto L
    35  L:
    36  	x := 1
    37  	_ = x
    38  }
    39  
    40  // goto across declaration not okay
    41  func _() {
    42  	goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration"
    43  	x := 1 // GCCGO_ERROR "defined here"
    44  	_ = x
    45  L:
    46  }
    47  
    48  // goto across declaration in inner scope okay
    49  func _() {
    50  	goto L
    51  	{
    52  		x := 1
    53  		_ = x
    54  	}
    55  L:
    56  }
    57  
    58  // goto across declaration after inner scope not okay
    59  func _() {
    60  	goto L // ERROR "goto L jumps over declaration of x at LINE+5|goto jumps over declaration"
    61  	{
    62  		x := 1
    63  		_ = x
    64  	}
    65  	x := 1 // GCCGO_ERROR "defined here"
    66  	_ = x
    67  L:
    68  }
    69  
    70  // goto across declaration in reverse okay
    71  func _() {
    72  L:
    73  	x := 1
    74  	_ = x
    75  	goto L
    76  }
    77  
    78  // error shows first offending variable
    79  func _() {
    80  	goto L // ERROR "goto L jumps over declaration of y at LINE+3|goto jumps over declaration"
    81  	x := 1 // GCCGO_ERROR "defined here"
    82  	_ = x
    83  	y := 1
    84  	_ = y
    85  L:
    86  }
    87  
    88  // goto not okay even if code path is dead
    89  func _() {
    90  	goto L // ERROR "goto L jumps over declaration of y at LINE+3|goto jumps over declaration"
    91  	x := 1 // GCCGO_ERROR "defined here"
    92  	_ = x
    93  	y := 1
    94  	_ = y
    95  	return
    96  L:
    97  }
    98  
    99  // goto into outer block okay
   100  func _() {
   101  	{
   102  		goto L
   103  	}
   104  L:
   105  }
   106  
   107  // goto backward into outer block okay
   108  func _() {
   109  L:
   110  	{
   111  		goto L
   112  	}
   113  }
   114  
   115  // goto into inner block not okay
   116  func _() {
   117  	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
   118  	{      // GCCGO_ERROR "block starts here"
   119  	L:
   120  	}
   121  }
   122  
   123  // goto backward into inner block still not okay
   124  func _() {
   125  	{ // GCCGO_ERROR "block starts here"
   126  	L:
   127  	}
   128  	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   129  }
   130  
   131  // error shows first (outermost) offending block
   132  func _() {
   133  	goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
   134  	{
   135  		{
   136  			{ // GCCGO_ERROR "block starts here"
   137  			L:
   138  			}
   139  		}
   140  	}
   141  }
   142  
   143  // error prefers block diagnostic over declaration diagnostic
   144  func _() {
   145  	goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
   146  	x := 1
   147  	_ = x
   148  	{ // GCCGO_ERROR "block starts here"
   149  	L:
   150  	}
   151  }
   152  
   153  // many kinds of blocks, all invalid to jump into or among,
   154  // but valid to jump out of
   155  
   156  // if
   157  
   158  func _() {
   159  L:
   160  	if true {
   161  		goto L
   162  	}
   163  }
   164  
   165  func _() {
   166  L:
   167  	if true {
   168  		goto L
   169  	} else {
   170  	}
   171  }
   172  
   173  func _() {
   174  L:
   175  	if false {
   176  	} else {
   177  		goto L
   178  	}
   179  }
   180  
   181  func _() {
   182  	goto L    // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
   183  	if true { // GCCGO_ERROR "block starts here"
   184  	L:
   185  	}
   186  }
   187  
   188  func _() {
   189  	goto L    // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
   190  	if true { // GCCGO_ERROR "block starts here"
   191  	L:
   192  	} else {
   193  	}
   194  }
   195  
   196  func _() {
   197  	goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
   198  	if true {
   199  	} else { // GCCGO_ERROR "block starts here"
   200  	L:
   201  	}
   202  }
   203  
   204  func _() {
   205  	if false { // GCCGO_ERROR "block starts here"
   206  	L:
   207  	} else {
   208  		goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   209  	}
   210  }
   211  
   212  func _() {
   213  	if true {
   214  		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
   215  	} else { // GCCGO_ERROR "block starts here"
   216  	L:
   217  	}
   218  }
   219  
   220  func _() {
   221  	if true {
   222  		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
   223  	} else if false { // GCCGO_ERROR "block starts here"
   224  	L:
   225  	}
   226  }
   227  
   228  func _() {
   229  	if true {
   230  		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
   231  	} else if false { // GCCGO_ERROR "block starts here"
   232  	L:
   233  	} else {
   234  	}
   235  }
   236  
   237  func _() {
   238  	// This one is tricky.  There is an implicit scope
   239  	// starting at the second if statement, and it contains
   240  	// the final else, so the outermost offending scope
   241  	// really is LINE+1 (like in the previous test),
   242  	// even though it looks like it might be LINE+3 instead.
   243  	if true {
   244  		goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
   245  	} else if false {
   246  	} else { // GCCGO_ERROR "block starts here"
   247  	L:
   248  	}
   249  }
   250  
   251  /* Want to enable these tests but gofmt mangles them.  Issue 1972.
   252  
   253  func _() {
   254  	// This one is okay, because the else is in the
   255  	// implicit whole-if block and has no inner block
   256  	// (no { }) around it.
   257  	if true {
   258  		goto L
   259  	} else
   260  		L:
   261  }
   262  
   263  func _() {
   264  	// Still not okay.
   265  	if true {	//// GCCGO_ERROR "block starts here"
   266  	L:
   267  	} else
   268  		goto L //// ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   269  }
   270  
   271  */
   272  
   273  // for
   274  
   275  func _() {
   276  	for {
   277  		goto L
   278  	}
   279  L:
   280  }
   281  
   282  func _() {
   283  	for {
   284  		goto L
   285  	L:
   286  	}
   287  }
   288  
   289  func _() {
   290  	for { // GCCGO_ERROR "block starts here"
   291  	L:
   292  	}
   293  	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   294  }
   295  
   296  func _() {
   297  	for { // GCCGO_ERROR "block starts here"
   298  		goto L
   299  	L1:
   300  	}
   301  L:
   302  	goto L1 // ERROR "goto L1 jumps into block starting at LINE-5|goto jumps into block"
   303  }
   304  
   305  func _() {
   306  	for i < n { // GCCGO_ERROR "block starts here"
   307  	L:
   308  	}
   309  	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   310  }
   311  
   312  func _() {
   313  	for i = 0; i < n; i++ { // GCCGO_ERROR "block starts here"
   314  	L:
   315  	}
   316  	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   317  }
   318  
   319  func _() {
   320  	for i = range x { // GCCGO_ERROR "block starts here"
   321  	L:
   322  	}
   323  	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   324  }
   325  
   326  func _() {
   327  	for i = range c { // GCCGO_ERROR "block starts here"
   328  	L:
   329  	}
   330  	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   331  }
   332  
   333  func _() {
   334  	for i = range m { // GCCGO_ERROR "block starts here"
   335  	L:
   336  	}
   337  	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   338  }
   339  
   340  func _() {
   341  	for i = range s { // GCCGO_ERROR "block starts here"
   342  	L:
   343  	}
   344  	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
   345  }
   346  
   347  // switch
   348  
   349  func _() {
   350  L:
   351  	switch i {
   352  	case 0:
   353  		goto L
   354  	}
   355  }
   356  
   357  func _() {
   358  L:
   359  	switch i {
   360  	case 0:
   361  
   362  	default:
   363  		goto L
   364  	}
   365  }
   366  
   367  func _() {
   368  	switch i {
   369  	case 0:
   370  
   371  	default:
   372  	L:
   373  		goto L
   374  	}
   375  }
   376  
   377  func _() {
   378  	switch i {
   379  	case 0:
   380  
   381  	default:
   382  		goto L
   383  	L:
   384  	}
   385  }
   386  
   387  func _() {
   388  	switch i {
   389  	case 0:
   390  		goto L
   391  	L:
   392  		;
   393  	default:
   394  	}
   395  }
   396  
   397  func _() {
   398  	goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
   399  	switch i {
   400  	case 0:
   401  	L: // GCCGO_ERROR "block starts here"
   402  	}
   403  }
   404  
   405  func _() {
   406  	goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
   407  	switch i {
   408  	case 0:
   409  	L: // GCCGO_ERROR "block starts here"
   410  		;
   411  	default:
   412  	}
   413  }
   414  
   415  func _() {
   416  	goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
   417  	switch i {
   418  	case 0:
   419  	default:
   420  	L: // GCCGO_ERROR "block starts here"
   421  	}
   422  }
   423  
   424  func _() {
   425  	switch i {
   426  	default:
   427  		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
   428  	case 0:
   429  	L: // GCCGO_ERROR "block starts here"
   430  	}
   431  }
   432  
   433  func _() {
   434  	switch i {
   435  	case 0:
   436  	L: // GCCGO_ERROR "block starts here"
   437  		;
   438  	default:
   439  		goto L // ERROR "goto L jumps into block starting at LINE-4|goto jumps into block"
   440  	}
   441  }
   442  
   443  // select
   444  // different from switch.  the statement has no implicit block around it.
   445  
   446  func _() {
   447  L:
   448  	select {
   449  	case <-c:
   450  		goto L
   451  	}
   452  }
   453  
   454  func _() {
   455  L:
   456  	select {
   457  	case c <- 1:
   458  
   459  	default:
   460  		goto L
   461  	}
   462  }
   463  
   464  func _() {
   465  	select {
   466  	case <-c:
   467  
   468  	default:
   469  	L:
   470  		goto L
   471  	}
   472  }
   473  
   474  func _() {
   475  	select {
   476  	case c <- 1:
   477  
   478  	default:
   479  		goto L
   480  	L:
   481  	}
   482  }
   483  
   484  func _() {
   485  	select {
   486  	case <-c:
   487  		goto L
   488  	L:
   489  		;
   490  	default:
   491  	}
   492  }
   493  
   494  func _() {
   495  	goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
   496  	select {
   497  	case c <- 1:
   498  	L: // GCCGO_ERROR "block starts here"
   499  	}
   500  }
   501  
   502  func _() {
   503  	goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
   504  	select {
   505  	case c <- 1:
   506  	L: // GCCGO_ERROR "block starts here"
   507  		;
   508  	default:
   509  	}
   510  }
   511  
   512  func _() {
   513  	goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
   514  	select {
   515  	case <-c:
   516  	default:
   517  	L: // GCCGO_ERROR "block starts here"
   518  	}
   519  }
   520  
   521  func _() {
   522  	select {
   523  	default:
   524  		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
   525  	case <-c:
   526  	L: // GCCGO_ERROR "block starts here"
   527  	}
   528  }
   529  
   530  func _() {
   531  	select {
   532  	case <-c:
   533  	L: // GCCGO_ERROR "block starts here"
   534  		;
   535  	default:
   536  		goto L // ERROR "goto L jumps into block starting at LINE-4|goto jumps into block"
   537  	}
   538  }
   539  

View as plain text