Source file test/live.go
Documentation: test
1 // errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off 2 // +build !ppc64,!ppc64le,!goexperiment.regabi,!goexperiment.regabidefer 3 4 // ppc64 needs a better tighten pass to make f18 pass 5 // rescheduling checks need to be turned off because there are some live variables across the inserted check call 6 // 7 // For register ABI, liveness info changes slightly. See live_regabi.go. 8 9 // Copyright 2014 The Go Authors. All rights reserved. 10 // Use of this source code is governed by a BSD-style 11 // license that can be found in the LICENSE file. 12 13 // liveness tests with inlining disabled. 14 // see also live2.go. 15 16 package main 17 18 func printnl() 19 20 //go:noescape 21 func printpointer(**int) 22 23 //go:noescape 24 func printintpointer(*int) 25 26 //go:noescape 27 func printstringpointer(*string) 28 29 //go:noescape 30 func printstring(string) 31 32 //go:noescape 33 func printbytepointer(*byte) 34 35 func printint(int) 36 37 func f1() { 38 var x *int // ERROR "stack object x \*int$" 39 printpointer(&x) // ERROR "live at call to printpointer: x$" 40 printpointer(&x) 41 } 42 43 func f2(b bool) { 44 if b { 45 printint(0) // nothing live here 46 return 47 } 48 var x *int // ERROR "stack object x \*int$" 49 printpointer(&x) // ERROR "live at call to printpointer: x$" 50 printpointer(&x) 51 } 52 53 func f3(b1, b2 bool) { 54 // Here x and y are ambiguously live. In previous go versions they 55 // were marked as live throughout the function to avoid being 56 // poisoned in GODEBUG=gcdead=1 mode; this is now no longer the 57 // case. 58 59 printint(0) 60 if b1 == false { 61 printint(0) 62 return 63 } 64 65 if b2 { 66 var x *int // ERROR "stack object x \*int$" 67 printpointer(&x) // ERROR "live at call to printpointer: x$" 68 printpointer(&x) 69 } else { 70 var y *int // ERROR "stack object y \*int$" 71 printpointer(&y) // ERROR "live at call to printpointer: y$" 72 printpointer(&y) 73 } 74 printint(0) // nothing is live here 75 } 76 77 // The old algorithm treated x as live on all code that 78 // could flow to a return statement, so it included the 79 // function entry and code above the declaration of x 80 // but would not include an indirect use of x in an infinite loop. 81 // Check that these cases are handled correctly. 82 83 func f4(b1, b2 bool) { // x not live here 84 if b2 { 85 printint(0) // x not live here 86 return 87 } 88 var z **int 89 x := new(int) // ERROR "stack object x \*int$" 90 *x = 42 91 z = &x 92 printint(**z) // ERROR "live at call to printint: x$" 93 if b2 { 94 printint(1) // x not live here 95 return 96 } 97 for { 98 printint(**z) // ERROR "live at call to printint: x$" 99 } 100 } 101 102 func f5(b1 bool) { 103 var z **int 104 if b1 { 105 x := new(int) // ERROR "stack object x \*int$" 106 *x = 42 107 z = &x 108 } else { 109 y := new(int) // ERROR "stack object y \*int$" 110 *y = 54 111 z = &y 112 } 113 printint(**z) // nothing live here 114 } 115 116 // confusion about the _ result used to cause spurious "live at entry to f6: _". 117 118 func f6() (_, y string) { 119 y = "hello" 120 return 121 } 122 123 // confusion about addressed results used to cause "live at entry to f7: x". 124 125 func f7() (x string) { // ERROR "stack object x string" 126 _ = &x 127 x = "hello" 128 return 129 } 130 131 // ignoring block returns used to cause "live at entry to f8: x, y". 132 133 func f8() (x, y string) { 134 return g8() 135 } 136 137 func g8() (string, string) 138 139 // ignoring block assignments used to cause "live at entry to f9: x" 140 // issue 7205 141 142 var i9 interface{} 143 144 func f9() bool { 145 g8() 146 x := i9 147 y := interface{}(g18()) // ERROR "live at call to convT2E: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$" 148 i9 = y // make y escape so the line above has to call convT2E 149 return x != y 150 } 151 152 // liveness formerly confused by UNDEF followed by RET, 153 // leading to "live at entry to f10: ~r1" (unnamed result). 154 155 func f10() string { 156 panic(1) 157 } 158 159 // liveness formerly confused by select, thinking runtime.selectgo 160 // can return to next instruction; it always jumps elsewhere. 161 // note that you have to use at least two cases in the select 162 // to get a true select; smaller selects compile to optimized helper functions. 163 164 var c chan *int 165 var b bool 166 167 // this used to have a spurious "live at entry to f11a: ~r0" 168 func f11a() *int { 169 select { // ERROR "stack object .autotmp_[0-9]+ \[2\]struct" 170 case <-c: 171 return nil 172 case <-c: 173 return nil 174 } 175 } 176 177 func f11b() *int { 178 p := new(int) 179 if b { 180 // At this point p is dead: the code here cannot 181 // get to the bottom of the function. 182 // This used to have a spurious "live at call to printint: p". 183 printint(1) // nothing live here! 184 select { // ERROR "stack object .autotmp_[0-9]+ \[2\]struct" 185 case <-c: 186 return nil 187 case <-c: 188 return nil 189 } 190 } 191 println(*p) 192 return nil 193 } 194 195 var sink *int 196 197 func f11c() *int { 198 p := new(int) 199 sink = p // prevent stack allocation, otherwise p is rematerializeable 200 if b { 201 // Unlike previous, the cases in this select fall through, 202 // so we can get to the println, so p is not dead. 203 printint(1) // ERROR "live at call to printint: p$" 204 select { // ERROR "live at call to selectgo: p$" "stack object .autotmp_[0-9]+ \[2\]struct" 205 case <-c: 206 case <-c: 207 } 208 } 209 println(*p) 210 return nil 211 } 212 213 // similarly, select{} does not fall through. 214 // this used to have a spurious "live at entry to f12: ~r0". 215 216 func f12() *int { 217 if b { 218 select {} 219 } else { 220 return nil 221 } 222 } 223 224 // incorrectly placed VARDEF annotations can cause missing liveness annotations. 225 // this used to be missing the fact that s is live during the call to g13 (because it is 226 // needed for the call to h13). 227 228 func f13() { 229 s := g14() 230 s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$" 231 } 232 233 func g13(string) string 234 func h13(string, string) string 235 236 // more incorrectly placed VARDEF. 237 238 func f14() { 239 x := g14() // ERROR "stack object x string$" 240 printstringpointer(&x) 241 } 242 243 func g14() 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 var mi map[interface{}]int 253 254 // str and iface are used to ensure that a temp is required for runtime calls below. 255 func str() string 256 func iface() interface{} 257 258 func f16() { 259 if b { 260 delete(mi, iface()) // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 261 } 262 delete(mi, iface()) 263 delete(mi, iface()) 264 } 265 266 var m2s map[string]*byte 267 var m2 map[[2]string]*byte 268 var x2 [2]string 269 var bp *byte 270 271 func f17a(p *byte) { // ERROR "live at entry to f17a: p$" 272 if b { 273 m2[x2] = p // ERROR "live at call to mapassign: p$" 274 } 275 m2[x2] = p // ERROR "live at call to mapassign: p$" 276 m2[x2] = p // ERROR "live at call to mapassign: p$" 277 } 278 279 func f17b(p *byte) { // ERROR "live at entry to f17b: p$" 280 // key temporary 281 if b { 282 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$" 283 } 284 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$" 285 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$" 286 } 287 288 func f17c() { 289 // key and value temporaries 290 if b { 291 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 292 } 293 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 294 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 295 } 296 297 func f17d() *byte 298 299 func g18() [2]string 300 301 func f18() { 302 // key temporary for mapaccess. 303 // temporary introduced by orderexpr. 304 var z *byte 305 if b { 306 z = m2[g18()] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 307 } 308 z = m2[g18()] 309 z = m2[g18()] 310 printbytepointer(z) 311 } 312 313 var ch chan *byte 314 315 // byteptr is used to ensure that a temp is required for runtime calls below. 316 func byteptr() *byte 317 318 func f19() { 319 // dest temporary for channel receive. 320 var z *byte 321 322 if b { 323 z = <-ch // ERROR "stack object .autotmp_[0-9]+ \*byte$" 324 } 325 z = <-ch 326 z = <-ch // ERROR "live at call to chanrecv1: .autotmp_[0-9]+$" 327 printbytepointer(z) 328 } 329 330 func f20() { 331 // src temporary for channel send 332 if b { 333 ch <- byteptr() // ERROR "stack object .autotmp_[0-9]+ \*byte$" 334 } 335 ch <- byteptr() 336 ch <- byteptr() 337 } 338 339 func f21() { 340 // key temporary for mapaccess using array literal key. 341 var z *byte 342 if b { 343 z = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 344 } 345 z = m2[[2]string{"x", "y"}] 346 z = m2[[2]string{"x", "y"}] 347 printbytepointer(z) 348 } 349 350 func f23() { 351 // key temporary for two-result map access using array literal key. 352 var z *byte 353 var ok bool 354 if b { 355 z, ok = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 356 } 357 z, ok = m2[[2]string{"x", "y"}] 358 z, ok = m2[[2]string{"x", "y"}] 359 printbytepointer(z) 360 print(ok) 361 } 362 363 func f24() { 364 // key temporary for map access using array literal key. 365 // value temporary too. 366 if b { 367 m2[[2]string{"x", "y"}] = nil // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 368 } 369 m2[[2]string{"x", "y"}] = nil 370 m2[[2]string{"x", "y"}] = nil 371 } 372 373 // Non-open-coded defers should not cause autotmps. (Open-coded defers do create extra autotmps). 374 func f25(b bool) { 375 for i := 0; i < 2; i++ { 376 // Put in loop to make sure defer is not open-coded 377 defer g25() 378 } 379 if b { 380 return 381 } 382 var x string 383 x = g14() 384 printstring(x) 385 return 386 } 387 388 func g25() 389 390 // non-escaping ... slices passed to function call should die on return, 391 // so that the temporaries do not stack and do not cause ambiguously 392 // live variables. 393 394 func f26(b bool) { 395 if b { 396 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "stack object .autotmp_[0-9]+ \[3\]interface \{\}$" 397 } 398 print26((*int)(nil), (*int)(nil), (*int)(nil)) 399 print26((*int)(nil), (*int)(nil), (*int)(nil)) 400 printnl() 401 } 402 403 //go:noescape 404 func print26(...interface{}) 405 406 // non-escaping closures passed to function call should die on return 407 408 func f27(b bool) { 409 x := 0 410 if b { 411 call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 412 } 413 call27(func() { x++ }) 414 call27(func() { x++ }) 415 printnl() 416 } 417 418 // but defer does escape to later execution in the function 419 420 func f27defer(b bool) { 421 x := 0 422 if b { 423 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 424 } 425 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 426 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+" 427 return // ERROR "live at call to call27: .autotmp_[0-9]+" 428 } 429 430 // and newproc (go) escapes to the heap 431 432 func f27go(b bool) { 433 x := 0 434 if b { 435 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newproc: &x$" 436 } 437 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" 438 printnl() 439 } 440 441 //go:noescape 442 func call27(func()) 443 444 // concatstring slice should die on return 445 446 var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string 447 448 func f28(b bool) { 449 if b { 450 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "stack object .autotmp_[0-9]+ \[10\]string$" 451 } 452 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) 453 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) 454 } 455 456 // map iterator should die on end of range loop 457 458 func f29(b bool) { 459 if b { 460 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ map.iter\[string\]int$" 461 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 462 } 463 } 464 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$" 465 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 466 } 467 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$" 468 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 469 } 470 } 471 472 // copy of array of pointers should die at end of range loop 473 var pstructarr [10]pstruct 474 475 // Struct size chosen to make pointer to element in pstructarr 476 // not computable by strength reduction. 477 type pstruct struct { 478 intp *int 479 _ [8]byte 480 } 481 482 func f30(b bool) { 483 // live temp during printintpointer(p): 484 // the internal iterator pointer if a pointer to pstruct in pstructarr 485 // can not be easily computed by strength reduction. 486 if b { 487 for _, p := range pstructarr { // ERROR "stack object .autotmp_[0-9]+ \[10\]pstruct$" 488 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 489 } 490 } 491 for _, p := range pstructarr { 492 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 493 } 494 for _, p := range pstructarr { 495 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 496 } 497 } 498 499 // conversion to interface should not leave temporary behind 500 501 func f31(b1, b2, b3 bool) { 502 if b1 { 503 g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 504 } 505 if b2 { 506 h31(g18()) // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$" 507 } 508 if b3 { 509 panic(g18()) 510 } 511 print(b3) 512 } 513 514 func g31(interface{}) 515 func h31(...interface{}) 516 517 // non-escaping partial functions passed to function call should die on return 518 519 type T32 int 520 521 func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$" 522 *t++ 523 } 524 525 var t32 T32 526 527 func f32(b bool) { 528 if b { 529 call32(t32.Inc) // ERROR "stack object .autotmp_[0-9]+ struct \{" 530 } 531 call32(t32.Inc) 532 call32(t32.Inc) 533 } 534 535 //go:noescape 536 func call32(func()) 537 538 // temporaries introduced during if conditions and && || expressions 539 // should die once the condition has been acted upon. 540 541 var m33 map[interface{}]int 542 543 func f33() { 544 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 545 printnl() 546 return 547 } else { 548 printnl() 549 } 550 printnl() 551 } 552 553 func f34() { 554 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 555 printnl() 556 return 557 } 558 printnl() 559 } 560 561 func f35() { 562 if m33[byteptr()] == 0 && // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 563 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 564 printnl() 565 return 566 } 567 printnl() 568 } 569 570 func f36() { 571 if m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 572 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 573 printnl() 574 return 575 } 576 printnl() 577 } 578 579 func f37() { 580 if (m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 581 m33[byteptr()] == 0) && // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 582 m33[byteptr()] == 0 { 583 printnl() 584 return 585 } 586 printnl() 587 } 588 589 // select temps should disappear in the case bodies 590 591 var c38 chan string 592 593 func fc38() chan string 594 func fi38(int) *string 595 func fb38() *bool 596 597 func f38(b bool) { 598 // we don't care what temps are printed on the lines with output. 599 // we care that the println lines have no live variables 600 // and therefore no output. 601 if b { 602 select { // ERROR "live at call to selectgo:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ \[4\]struct \{" 603 case <-fc38(): 604 printnl() 605 case fc38() <- *fi38(1): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$" 606 printnl() 607 case *fi38(2) = <-fc38(): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$" 608 printnl() 609 case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" 610 printnl() 611 } 612 printnl() 613 } 614 printnl() 615 } 616 617 // issue 8097: mishandling of x = x during return. 618 619 func f39() (x []int) { 620 x = []int{1} 621 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$" 622 return x 623 } 624 625 func f39a() (x []int) { 626 x = []int{1} 627 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$" 628 return 629 } 630 631 func f39b() (x [10]*int) { 632 x = [10]*int{} 633 x[0] = new(int) // ERROR "live at call to newobject: x$" 634 printnl() // ERROR "live at call to printnl: x$" 635 return x 636 } 637 638 func f39c() (x [10]*int) { 639 x = [10]*int{} 640 x[0] = new(int) // ERROR "live at call to newobject: x$" 641 printnl() // ERROR "live at call to printnl: x$" 642 return 643 } 644 645 // issue 8142: lost 'addrtaken' bit on inlined variables. 646 // no inlining in this test, so just checking that non-inlined works. 647 648 type T40 struct { 649 m map[int]int 650 } 651 652 //go:noescape 653 func useT40(*T40) 654 655 func newT40() *T40 { 656 ret := T40{} 657 ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$" 658 return &ret 659 } 660 661 func bad40() { 662 t := newT40() 663 _ = t 664 printnl() 665 } 666 667 func good40() { 668 ret := T40{} // ERROR "stack object ret T40$" 669 ret.m = make(map[int]int) // ERROR "live at call to fastrand: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$" 670 t := &ret 671 printnl() // ERROR "live at call to printnl: ret$" 672 // Note: ret is live at the printnl because the compiler moves &ret 673 // from before the printnl to after. 674 useT40(t) 675 } 676 677 func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$" 678 ddd2(x, y) // ERROR "stack object .autotmp_[0-9]+ \[2\]\*int$" 679 printnl() 680 // Note: no .?autotmp live at printnl. See issue 16996. 681 } 682 func ddd2(a ...*int) { // ERROR "live at entry to ddd2: a$" 683 sink = a[0] 684 } 685 686 // issue 16016: autogenerated wrapper should have arguments live 687 type T struct{} 688 689 func (*T) Foo(ptr *int) {} 690 691 type R struct{ *T } // ERRORAUTO "live at entry to \(\*R\)\.Foo: \.this ptr" "live at entry to R\.Foo: \.this ptr" 692 693 // issue 18860: output arguments must be live all the time if there is a defer. 694 // In particular, at printint r must be live. 695 func f41(p, q *int) (r *int) { // ERROR "live at entry to f41: p q$" 696 r = p 697 defer func() { 698 recover() 699 }() 700 printint(0) // ERROR "live at call to printint: q r .autotmp_[0-9]+$" 701 r = q 702 return // ERROR "live at call to f41.func1: r .autotmp_[0-9]+$" 703 } 704 705 func f42() { 706 var p, q, r int 707 f43([]*int{&p, &q, &r}) // ERROR "stack object .autotmp_[0-9]+ \[3\]\*int$" 708 f43([]*int{&p, &r, &q}) 709 f43([]*int{&q, &p, &r}) 710 } 711 712 //go:noescape 713 func f43(a []*int) 714 715 // Assigning to a sub-element that makes up an entire local variable 716 // should clobber that variable. 717 func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f" 718 type T struct { 719 s [1][2]*int 720 } 721 ret := T{} 722 ret.s[0] = f() 723 return ret // ERROR "stack object .autotmp_[0-9]+ T" 724 } 725