Home | History | Annotate | Download | only in test
      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