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