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 14package main 15 16var ( 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 25func _() { 26 x := 1 27 goto L 28L: 29 _ = x 30} 31 32// goto before declaration okay 33func _() { 34 goto L 35L: 36 x := 1 37 _ = x 38} 39 40// goto across declaration not okay 41func _() { 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 45L: 46} 47 48// goto across declaration in inner scope okay 49func _() { 50 goto L 51 { 52 x := 1 53 _ = x 54 } 55L: 56} 57 58// goto across declaration after inner scope not okay 59func _() { 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 67L: 68} 69 70// goto across declaration in reverse okay 71func _() { 72L: 73 x := 1 74 _ = x 75 goto L 76} 77 78// error shows first offending variable 79func _() { 80 goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration" 81 x := 1 // GCCGO_ERROR "defined here" 82 _ = x 83 y := 1 84 _ = y 85L: 86} 87 88// goto not okay even if code path is dead 89func _() { 90 goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration" 91 x := 1 // GCCGO_ERROR "defined here" 92 _ = x 93 y := 1 94 _ = y 95 return 96L: 97} 98 99// goto into outer block okay 100func _() { 101 { 102 goto L 103 } 104L: 105} 106 107// goto backward into outer block okay 108func _() { 109L: 110 { 111 goto L 112 } 113} 114 115// goto into inner block not okay 116func _() { 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 124func _() { 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 132func _() { 133 goto L // ERROR "goto L jumps into block starting at LINE+1|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 144func _() { 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 158func _() { 159L: 160 if true { 161 goto L 162 } 163} 164 165func _() { 166L: 167 if true { 168 goto L 169 } else { 170 } 171} 172 173func _() { 174L: 175 if false { 176 } else { 177 goto L 178 } 179} 180 181func _() { 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 188func _() { 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 196func _() { 197 goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" 198 if true { 199 } else { // GCCGO_ERROR "block starts here" 200 L: 201 } 202} 203 204func _() { 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 212func _() { 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 220func _() { 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 228func _() { 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 237func _() { 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+1|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 253func _() { 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 263func _() { 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 275func _() { 276 for { 277 goto L 278 } 279L: 280} 281 282func _() { 283 for { 284 goto L 285 L: 286 } 287} 288 289func _() { 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 296func _() { 297 for { // GCCGO_ERROR "block starts here" 298 goto L 299 L1: 300 } 301L: 302 goto L1 // ERROR "goto L1 jumps into block starting at LINE-5|goto jumps into block" 303} 304 305func _() { 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 312func _() { 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 319func _() { 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 326func _() { 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 333func _() { 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 340func _() { 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 349func _() { 350L: 351 switch i { 352 case 0: 353 goto L 354 } 355} 356 357func _() { 358L: 359 switch i { 360 case 0: 361 362 default: 363 goto L 364 } 365} 366 367func _() { 368 switch i { 369 case 0: 370 371 default: 372 L: 373 goto L 374 } 375} 376 377func _() { 378 switch i { 379 case 0: 380 381 default: 382 goto L 383 L: 384 } 385} 386 387func _() { 388 switch i { 389 case 0: 390 goto L 391 L: 392 ; 393 default: 394 } 395} 396 397func _() { 398 goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" 399 switch i { 400 case 0: 401 L: // GCCGO_ERROR "block starts here" 402 } 403} 404 405func _() { 406 goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" 407 switch i { 408 case 0: 409 L: // GCCGO_ERROR "block starts here" 410 ; 411 default: 412 } 413} 414 415func _() { 416 goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block" 417 switch i { 418 case 0: 419 default: 420 L: // GCCGO_ERROR "block starts here" 421 } 422} 423 424func _() { 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 433func _() { 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 446func _() { 447L: 448 select { 449 case <-c: 450 goto L 451 } 452} 453 454func _() { 455L: 456 select { 457 case c <- 1: 458 459 default: 460 goto L 461 } 462} 463 464func _() { 465 select { 466 case <-c: 467 468 default: 469 L: 470 goto L 471 } 472} 473 474func _() { 475 select { 476 case c <- 1: 477 478 default: 479 goto L 480 L: 481 } 482} 483 484func _() { 485 select { 486 case <-c: 487 goto L 488 L: 489 ; 490 default: 491 } 492} 493 494func _() { 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 502func _() { 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 512func _() { 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 521func _() { 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 530func _() { 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