github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/test/live.go (about) 1 // errorcheck -0 -l -live -wb=0 2 3 // Copyright 2014 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 // liveness tests with inlining disabled. 8 // see also live2.go. 9 10 package main 11 12 func printnl() 13 14 //go:noescape 15 func printpointer(**int) 16 17 //go:noescape 18 func printintpointer(*int) 19 20 //go:noescape 21 func printstringpointer(*string) 22 23 //go:noescape 24 func printstring(string) 25 26 //go:noescape 27 func printbytepointer(*byte) 28 29 func printint(int) 30 31 func f1() { 32 var x *int 33 printpointer(&x) // ERROR "live at call to printpointer: x$" 34 printpointer(&x) // ERROR "live at call to printpointer: x$" 35 } 36 37 func f2(b bool) { 38 if b { 39 printint(0) // nothing live here 40 return 41 } 42 var x *int 43 printpointer(&x) // ERROR "live at call to printpointer: x$" 44 printpointer(&x) // ERROR "live at call to printpointer: x$" 45 } 46 47 func f3(b bool) { 48 // Because x and y are ambiguously live, they appear 49 // live throughout the function, to avoid being poisoned 50 // in GODEBUG=gcdead=1 mode. 51 52 printint(0) // ERROR "live at call to printint: x y$" 53 if b == false { 54 printint(0) // ERROR "live at call to printint: x y$" 55 return 56 } 57 58 if b { 59 var x *int 60 printpointer(&x) // ERROR "live at call to printpointer: x y$" 61 printpointer(&x) // ERROR "live at call to printpointer: x y$" 62 } else { 63 var y *int 64 printpointer(&y) // ERROR "live at call to printpointer: x y$" 65 printpointer(&y) // ERROR "live at call to printpointer: x y$" 66 } 67 printint(0) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live" 68 } 69 70 // The old algorithm treated x as live on all code that 71 // could flow to a return statement, so it included the 72 // function entry and code above the declaration of x 73 // but would not include an indirect use of x in an infinite loop. 74 // Check that these cases are handled correctly. 75 76 func f4(b1, b2 bool) { // x not live here 77 if b2 { 78 printint(0) // x not live here 79 return 80 } 81 var z **int 82 x := new(int) 83 *x = 42 84 z = &x 85 printint(**z) // ERROR "live at call to printint: x z$" 86 if b2 { 87 printint(1) // ERROR "live at call to printint: x$" 88 return 89 } 90 for { 91 printint(**z) // ERROR "live at call to printint: x z$" 92 } 93 } 94 95 func f5(b1 bool) { 96 var z **int 97 if b1 { 98 x := new(int) 99 *x = 42 100 z = &x 101 } else { 102 y := new(int) 103 *y = 54 104 z = &y 105 } 106 printint(**z) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live" 107 } 108 109 // confusion about the _ result used to cause spurious "live at entry to f6: _". 110 111 func f6() (_, y string) { 112 y = "hello" 113 return 114 } 115 116 // confusion about addressed results used to cause "live at entry to f7: x". 117 118 func f7() (x string) { 119 _ = &x 120 x = "hello" 121 return 122 } 123 124 // ignoring block returns used to cause "live at entry to f8: x, y". 125 126 func f8() (x, y string) { 127 return g8() 128 } 129 130 func g8() (string, string) 131 132 // ignoring block assignments used to cause "live at entry to f9: x" 133 // issue 7205 134 135 var i9 interface{} 136 137 func f9() bool { 138 g8() 139 x := i9 140 // using complex number in comparison so that 141 // there is always a convT2E, no matter what the 142 // interface rules are. 143 return x != 99.0i // ERROR "live at call to convT2E: x" 144 } 145 146 // liveness formerly confused by UNDEF followed by RET, 147 // leading to "live at entry to f10: ~r1" (unnamed result). 148 149 func f10() string { 150 panic(1) 151 } 152 153 // liveness formerly confused by select, thinking runtime.selectgo 154 // can return to next instruction; it always jumps elsewhere. 155 // note that you have to use at least two cases in the select 156 // to get a true select; smaller selects compile to optimized helper functions. 157 158 var c chan *int 159 var b bool 160 161 // this used to have a spurious "live at entry to f11a: ~r0" 162 func f11a() *int { 163 select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp" 164 case <-c: // ERROR "live at call to selectrecv: autotmp" 165 return nil 166 case <-c: // ERROR "live at call to selectrecv: autotmp" 167 return nil 168 } 169 } 170 171 func f11b() *int { 172 p := new(int) 173 if b { 174 // At this point p is dead: the code here cannot 175 // get to the bottom of the function. 176 // This used to have a spurious "live at call to printint: p". 177 printint(1) // nothing live here! 178 select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp" 179 case <-c: // ERROR "live at call to selectrecv: autotmp" 180 return nil 181 case <-c: // ERROR "live at call to selectrecv: autotmp" 182 return nil 183 } 184 } 185 println(*p) 186 return nil 187 } 188 189 func f11c() *int { 190 p := new(int) 191 if b { 192 // Unlike previous, the cases in this select fall through, 193 // so we can get to the println, so p is not dead. 194 printint(1) // ERROR "live at call to printint: p" 195 select { // ERROR "live at call to newselect: autotmp.* p" "live at call to selectgo: autotmp.* p" 196 case <-c: // ERROR "live at call to selectrecv: autotmp.* p" 197 case <-c: // ERROR "live at call to selectrecv: autotmp.* p" 198 } 199 } 200 println(*p) 201 return nil 202 } 203 204 // similarly, select{} does not fall through. 205 // this used to have a spurious "live at entry to f12: ~r0". 206 207 func f12() *int { 208 if b { 209 select {} 210 } else { 211 return nil 212 } 213 } 214 215 // incorrectly placed VARDEF annotations can cause missing liveness annotations. 216 // this used to be missing the fact that s is live during the call to g13 (because it is 217 // needed for the call to h13). 218 219 func f13() { 220 s := "hello" 221 s = h13(s, g13(s)) // ERROR "live at call to g13: s" 222 } 223 224 func g13(string) string 225 func h13(string, string) string 226 227 // more incorrectly placed VARDEF. 228 229 func f14() { 230 x := g14() 231 printstringpointer(&x) // ERROR "live at call to printstringpointer: x" 232 } 233 234 func g14() string 235 236 func f15() { 237 var x string 238 _ = &x 239 x = g15() // ERROR "live at call to g15: x" 240 printstring(x) // ERROR "live at call to printstring: x" 241 } 242 243 func g15() string 244 245 // Checking that various temporaries do not persist or cause 246 // ambiguously live values that must be zeroed. 247 // The exact temporary names are inconsequential but we are 248 // trying to check that there is only one at any given site, 249 // and also that none show up in "ambiguously live" messages. 250 251 var m map[string]int 252 253 func f16() { 254 if b { 255 delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" 256 } 257 delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" 258 delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" 259 } 260 261 var m2s map[string]*byte 262 var m2 map[[2]string]*byte 263 var x2 [2]string 264 var bp *byte 265 266 func f17a() { 267 // value temporary only 268 if b { 269 m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 270 } 271 m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 272 m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 273 } 274 275 func f17b() { 276 // key temporary only 277 if b { 278 m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 279 } 280 m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 281 m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 282 } 283 284 func f17c() { 285 // key and value temporaries 286 if b { 287 m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 288 } 289 m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 290 m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 291 } 292 293 func g18() [2]string 294 295 func f18() { 296 // key temporary for mapaccess. 297 // temporary introduced by orderexpr. 298 var z *byte 299 if b { 300 z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 301 } 302 z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 303 z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 304 printbytepointer(z) 305 } 306 307 var ch chan *byte 308 309 func f19() { 310 // dest temporary for channel receive. 311 var z *byte 312 313 if b { 314 z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" 315 } 316 z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" 317 z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" 318 printbytepointer(z) 319 } 320 321 func f20() { 322 // src temporary for channel send 323 if b { 324 ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" 325 } 326 ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" 327 ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" 328 } 329 330 func f21() { 331 // key temporary for mapaccess using array literal key. 332 var z *byte 333 if b { 334 z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 335 } 336 z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 337 z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 338 printbytepointer(z) 339 } 340 341 func f23() { 342 // key temporary for two-result map access using array literal key. 343 var z *byte 344 var ok bool 345 if b { 346 z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" 347 } 348 z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" 349 z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" 350 printbytepointer(z) 351 print(ok) 352 } 353 354 func f24() { 355 // key temporary for map access using array literal key. 356 // value temporary too. 357 if b { 358 m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 359 } 360 m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 361 m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 362 } 363 364 // defer should not cause spurious ambiguously live variables 365 366 func f25(b bool) { 367 defer g25() 368 if b { 369 return 370 } 371 var x string 372 _ = &x 373 x = g15() // ERROR "live at call to g15: x" 374 printstring(x) // ERROR "live at call to printstring: x" 375 } // ERROR "live at call to deferreturn: x" 376 377 func g25() 378 379 // non-escaping ... slices passed to function call should die on return, 380 // so that the temporaries do not stack and do not cause ambiguously 381 // live variables. 382 383 func f26(b bool) { 384 if b { 385 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" 386 } 387 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" 388 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" 389 printnl() 390 } 391 392 //go:noescape 393 func print26(...interface{}) 394 395 // non-escaping closures passed to function call should die on return 396 397 func f27(b bool) { 398 x := 0 399 if b { 400 call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" 401 } 402 call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" 403 call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" 404 printnl() 405 } 406 407 // but defer does escape to later execution in the function 408 409 func f27defer(b bool) { 410 x := 0 411 if b { 412 defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$" 413 } 414 defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live" 415 printnl() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$" 416 } // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" 417 418 // and newproc (go) escapes to the heap 419 420 func f27go(b bool) { 421 x := 0 422 if b { 423 go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$" 424 } 425 go call27(func() { x++ }) // ERROR "live at call to newobject: &x" 426 printnl() 427 } 428 429 //go:noescape 430 func call27(func()) 431 432 // concatstring slice should die on return 433 434 var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string 435 436 func f28(b bool) { 437 if b { 438 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" 439 } 440 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" 441 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" 442 } 443 444 // map iterator should die on end of range loop 445 446 func f29(b bool) { 447 if b { 448 for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$" 449 printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$" 450 } 451 } 452 for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$" 453 printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$" 454 } 455 for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$" 456 printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$" 457 } 458 } 459 460 // copy of array of pointers should die at end of range loop 461 462 var ptrarr [10]*int 463 464 func f30(b bool) { 465 // two live temps during print(p): 466 // the copy of ptrarr and the internal iterator pointer. 467 if b { 468 for _, p := range ptrarr { 469 printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$" 470 } 471 } 472 for _, p := range ptrarr { 473 printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$" 474 } 475 for _, p := range ptrarr { 476 printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$" 477 } 478 } 479 480 // conversion to interface should not leave temporary behind 481 482 func f31(b1, b2, b3 bool) { 483 if b1 { 484 g31("a") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to g31: autotmp_[0-9]+$" 485 } 486 if b2 { 487 h31("b") // ERROR "live at call to newobject: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$" 488 } 489 if b3 { 490 panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$" 491 } 492 print(b3) 493 } 494 495 func g31(interface{}) 496 func h31(...interface{}) 497 498 // non-escaping partial functions passed to function call should die on return 499 500 type T32 int 501 502 func (t *T32) Inc() { // ERROR "live at entry" 503 *t++ 504 } 505 506 var t32 T32 507 508 func f32(b bool) { 509 if b { 510 call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" 511 } 512 call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" 513 call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" 514 } 515 516 //go:noescape 517 func call32(func()) 518 519 // temporaries introduced during if conditions and && || expressions 520 // should die once the condition has been acted upon. 521 522 var m33 map[interface{}]int 523 524 func f33() { 525 if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 526 printnl() 527 return 528 } else { 529 printnl() 530 } 531 printnl() 532 } 533 534 func f34() { 535 if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 536 printnl() 537 return 538 } 539 printnl() 540 } 541 542 func f35() { 543 if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 544 printnl() 545 return 546 } 547 printnl() 548 } 549 550 func f36() { 551 if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 552 printnl() 553 return 554 } 555 printnl() 556 } 557 558 func f37() { 559 if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 560 printnl() 561 return 562 } 563 printnl() 564 } 565 566 // select temps should disappear in the case bodies 567 568 var c38 chan string 569 570 func fc38() chan string 571 func fi38(int) *string 572 func fb38() *bool 573 574 func f38(b bool) { 575 // we don't care what temps are printed on the lines with output. 576 // we care that the println lines have no live variables 577 // and therefore no output. 578 if b { 579 select { // ERROR "live at call" 580 case <-fc38(): // ERROR "live at call" 581 printnl() 582 case fc38() <- *fi38(1): // ERROR "live at call" 583 printnl() 584 case *fi38(2) = <-fc38(): // ERROR "live at call" 585 printnl() 586 case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call" 587 printnl() 588 } 589 printnl() 590 } 591 printnl() 592 } 593 594 // issue 8097: mishandling of x = x during return. 595 596 func f39() (x []int) { 597 x = []int{1} 598 printnl() // ERROR "live at call to printnl: x" 599 return x 600 } 601 602 func f39a() (x []int) { 603 x = []int{1} 604 printnl() // ERROR "live at call to printnl: x" 605 return 606 } 607 608 func f39b() (x [10]*int) { 609 x = [10]*int{} 610 x[0] = new(int) // ERROR "live at call to newobject: x" 611 printnl() // ERROR "live at call to printnl: x" 612 return x 613 } 614 615 func f39c() (x [10]*int) { 616 x = [10]*int{} 617 x[0] = new(int) // ERROR "live at call to newobject: x" 618 printnl() // ERROR "live at call to printnl: x" 619 return 620 } 621 622 // issue 8142: lost 'addrtaken' bit on inlined variables. 623 // no inlining in this test, so just checking that non-inlined works. 624 625 type T40 struct { 626 m map[int]int 627 } 628 629 func newT40() *T40 { 630 ret := T40{} 631 ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret" 632 return &ret 633 } 634 635 func bad40() { 636 t := newT40() 637 _ = t 638 printnl() 639 } 640 641 func good40() { 642 ret := T40{} 643 ret.m = make(map[int]int) // ERROR "live at call to makemap: ret" 644 t := &ret 645 printnl() // ERROR "live at call to printnl: ret" 646 _ = t 647 }