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 17package main 18 19func printnl() 20 21//go:noescape 22func printpointer(**int) 23 24//go:noescape 25func printintpointer(*int) 26 27//go:noescape 28func printstringpointer(*string) 29 30//go:noescape 31func printstring(string) 32 33//go:noescape 34func printbytepointer(*byte) 35 36func printint(int) 37 38func 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 44func 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 54func 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 84func 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 103func 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 119func 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 126func 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 134func f8() (x, y string) { 135 return g8() 136} 137 138func g8() (string, string) 139 140// ignoring block assignments used to cause "live at entry to f9: x" 141// issue 7205 142 143var i9 interface{} 144 145func 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 156func 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 165var c chan *int 166var b bool 167 168// this used to have a spurious "live at entry to f11a: ~r0" 169func 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 178func 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 196var sink *int 197 198func 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 217func 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 229func f13() { 230 s := g14() 231 s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$" 232} 233 234func g13(string) string 235func h13(string, string) string 236 237// more incorrectly placed VARDEF. 238 239func f14() { 240 x := g14() // ERROR "stack object x string$" 241 printstringpointer(&x) 242} 243 244func 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 252var m map[string]int 253var mi map[interface{}]int 254 255// str and iface are used to ensure that a temp is required for runtime calls below. 256func str() string 257func iface() interface{} 258 259func 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 267var m2s map[string]*byte 268var m2 map[[2]string]*byte 269var x2 [2]string 270var bp *byte 271 272func 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 280func 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 289func 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 298func f17d() *byte 299 300func g18() [2]string 301 302func 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 314var ch chan *byte 315 316// byteptr is used to ensure that a temp is required for runtime calls below. 317func byteptr() *byte 318 319func 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 331func 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 340func 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 351func 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 364func 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). 375func 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 389func 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 395func 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 405func print26(...interface{}) 406 407// non-escaping closures passed to function call should die on return 408 409func 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 421func 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 433func 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 443func call27(func()) 444 445// concatstring slice should die on return 446 447var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string 448 449func 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 459func 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 474var pstructarr [10]pstruct 475 476// Struct size chosen to make pointer to element in pstructarr 477// not computable by strength reduction. 478type pstruct struct { 479 intp *int 480 _ [8]byte 481} 482 483func 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 502func 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 515func g31(interface{}) 516func h31(...interface{}) 517 518// non-escaping partial functions passed to function call should die on return 519 520type T32 int 521 522func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$" 523 *t++ 524} 525 526var t32 T32 527 528func 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 537func call32(func()) 538 539// temporaries introduced during if conditions and && || expressions 540// should die once the condition has been acted upon. 541 542var m33 map[interface{}]int 543 544func 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 554func f34() { 555 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 556 printnl() 557 return 558 } 559 printnl() 560} 561 562func 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 571func 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 580func 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 592var c38 chan string 593 594func fc38() chan string 595func fi38(int) *string 596func fb38() *bool 597 598func 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 620func f39() (x []int) { 621 x = []int{1} 622 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$" 623 return x 624} 625 626func f39a() (x []int) { 627 x = []int{1} 628 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$" 629 return 630} 631 632func 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 639func 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 649type T40 struct { 650 m map[int]int 651} 652 653//go:noescape 654func useT40(*T40) 655 656func 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 662func bad40() { 663 t := newT40() 664 _ = t 665 printnl() 666} 667 668func 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 678func 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} 683func 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 688type T struct{} 689 690func (*T) Foo(ptr *int) {} 691 692type 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. 696func 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 706func 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 714func f43(a []*int) 715 716// Assigning to a sub-element that makes up an entire local variable 717// should clobber that variable. 718func 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