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