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