Source file test/live_regabi.go
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 12 package main 13 14 import "runtime" 15 16 func printnl() 17 18 //go:noescape 19 func printpointer(**int) 20 21 //go:noescape 22 func printintpointer(*int) 23 24 //go:noescape 25 func printstringpointer(*string) 26 27 //go:noescape 28 func printstring(string) 29 30 //go:noescape 31 func printbytepointer(*byte) 32 33 func printint(int) 34 35 func 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 41 func 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 51 func 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 81 func 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 100 func 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 116 func 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 123 func 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 131 func f8() (x, y string) { 132 return g8() 133 } 134 135 func g8() (string, string) 136 137 // ignoring block assignments used to cause "live at entry to f9: x" 138 // issue 7205 139 140 var i9 interface{} 141 142 func 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 153 func 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 162 var c chan *int 163 var b bool 164 165 // this used to have a spurious "live at entry to f11a: ~r0" 166 func 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 175 func 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 193 var sink *int 194 195 func 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 214 func 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 226 func f13() { 227 s := g14() 228 s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$" 229 } 230 231 func g13(string) string 232 func h13(string, string) string 233 234 // more incorrectly placed VARDEF. 235 236 func f14() { 237 x := g14() // ERROR "stack object x string$" 238 printstringpointer(&x) 239 } 240 241 func 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 249 var m map[string]int 250 var mi map[interface{}]int 251 252 // str and iface are used to ensure that a temp is required for runtime calls below. 253 func str() string 254 func iface() interface{} 255 256 func 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 264 var m2s map[string]*byte 265 var m2 map[[2]string]*byte 266 var x2 [2]string 267 var bp *byte 268 269 func 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 277 func 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 } 283 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$" 284 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$" 285 } 286 287 func f17c() { 288 // key and value temporaries 289 if b { 290 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 291 } 292 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 293 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$" 294 } 295 296 func f17d() *byte 297 298 func g18() [2]string 299 300 func f18() { 301 // key temporary for mapaccess. 302 // temporary introduced by orderexpr. 303 var z *byte 304 if b { 305 z = m2[g18()] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 306 } 307 z = m2[g18()] 308 z = m2[g18()] 309 printbytepointer(z) 310 } 311 312 var ch chan *byte 313 314 // byteptr is used to ensure that a temp is required for runtime calls below. 315 func byteptr() *byte 316 317 func f19() { 318 // dest temporary for channel receive. 319 var z *byte 320 321 if b { 322 z = <-ch // ERROR "stack object .autotmp_[0-9]+ \*byte$" 323 } 324 z = <-ch 325 z = <-ch // ERROR "live at call to chanrecv1: .autotmp_[0-9]+$" 326 printbytepointer(z) 327 } 328 329 func f20() { 330 // src temporary for channel send 331 if b { 332 ch <- byteptr() // ERROR "stack object .autotmp_[0-9]+ \*byte$" 333 } 334 ch <- byteptr() 335 ch <- byteptr() 336 } 337 338 func f21(x, y string) { // ERROR "live at entry to f21: x y" 339 // key temporary for mapaccess using array literal key. 340 var z *byte 341 if b { 342 z = m2[[2]string{x, y}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 343 } 344 z = m2[[2]string{"x", "y"}] 345 z = m2[[2]string{"x", "y"}] 346 printbytepointer(z) 347 } 348 349 func f21b() { 350 // key temporary for mapaccess using array literal key. 351 var z *byte 352 if b { 353 z = m2[[2]string{"x", "y"}] 354 } 355 z = m2[[2]string{"x", "y"}] 356 z = m2[[2]string{"x", "y"}] 357 printbytepointer(z) 358 } 359 360 func f23(x, y string) { // ERROR "live at entry to f23: x y" 361 // key temporary for two-result map access using array literal key. 362 var z *byte 363 var ok bool 364 if b { 365 z, ok = m2[[2]string{x, y}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 366 } 367 z, ok = m2[[2]string{"x", "y"}] 368 z, ok = m2[[2]string{"x", "y"}] 369 printbytepointer(z) 370 print(ok) 371 } 372 373 func f23b() { 374 // key temporary for two-result map access using array literal key. 375 var z *byte 376 var ok bool 377 if b { 378 z, ok = m2[[2]string{"x", "y"}] 379 } 380 z, ok = m2[[2]string{"x", "y"}] 381 z, ok = m2[[2]string{"x", "y"}] 382 printbytepointer(z) 383 print(ok) 384 } 385 386 func f24(x, y string) { // ERROR "live at entry to f24: x y" 387 // key temporary for map access using array lit3ral key. 388 // value temporary too. 389 if b { 390 m2[[2]string{x, y}] = nil // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 391 } 392 m2[[2]string{"x", "y"}] = nil 393 m2[[2]string{"x", "y"}] = nil 394 } 395 396 func f24b() { 397 // key temporary for map access using array literal key. 398 // value temporary too. 399 if b { 400 m2[[2]string{"x", "y"}] = nil 401 } 402 m2[[2]string{"x", "y"}] = nil 403 m2[[2]string{"x", "y"}] = nil 404 } 405 406 // Non-open-coded defers should not cause autotmps. (Open-coded defers do create extra autotmps). 407 func f25(b bool) { 408 for i := 0; i < 2; i++ { 409 // Put in loop to make sure defer is not open-coded 410 defer g25() 411 } 412 if b { 413 return 414 } 415 var x string 416 x = g14() 417 printstring(x) 418 return 419 } 420 421 func g25() 422 423 // non-escaping ... slices passed to function call should die on return, 424 // so that the temporaries do not stack and do not cause ambiguously 425 // live variables. 426 427 func f26(b bool) { 428 if b { 429 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "stack object .autotmp_[0-9]+ \[3\]interface \{\}$" 430 } 431 print26((*int)(nil), (*int)(nil), (*int)(nil)) 432 print26((*int)(nil), (*int)(nil), (*int)(nil)) 433 printnl() 434 } 435 436 //go:noescape 437 func print26(...interface{}) 438 439 // non-escaping closures passed to function call should die on return 440 441 func f27(b bool) { 442 x := 0 443 if b { 444 call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 445 } 446 call27(func() { x++ }) 447 call27(func() { x++ }) 448 printnl() 449 } 450 451 // but defer does escape to later execution in the function 452 453 func f27defer(b bool) { 454 x := 0 455 if b { 456 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 457 } 458 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" 459 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+" 460 return // ERROR "live at indirect call: .autotmp_[0-9]+" 461 } 462 463 // and newproc (go) escapes to the heap 464 465 func f27go(b bool) { 466 x := 0 467 if b { 468 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 469 } 470 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 471 printnl() 472 } 473 474 //go:noescape 475 func call27(func()) 476 477 // concatstring slice should die on return 478 479 var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string 480 481 func f28(b bool) { 482 if b { 483 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "stack object .autotmp_[0-9]+ \[10\]string$" 484 } 485 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) 486 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) 487 } 488 489 // map iterator should die on end of range loop 490 491 func f29(b bool) { 492 if b { 493 for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ (runtime.hiter|internal/runtime/maps.Iter)$" 494 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 495 } 496 } 497 for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$" 498 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 499 } 500 for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$" 501 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$" 502 } 503 } 504 505 // copy of array of pointers should die at end of range loop 506 var pstructarr [10]pstruct 507 508 // Struct size chosen to make pointer to element in pstructarr 509 // not computable by strength reduction. 510 type pstruct struct { 511 intp *int 512 _ [8]byte 513 } 514 515 func f30(b bool) { 516 // live temp during printintpointer(p): 517 // the internal iterator pointer if a pointer to pstruct in pstructarr 518 // can not be easily computed by strength reduction. 519 if b { 520 for _, p := range pstructarr { // ERROR "stack object .autotmp_[0-9]+ \[10\]pstruct$" 521 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 522 } 523 } 524 for _, p := range pstructarr { 525 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 526 } 527 for _, p := range pstructarr { 528 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$" 529 } 530 } 531 532 // conversion to interface should not leave temporary behind 533 534 func f31(b1, b2, b3 bool) { 535 if b1 { 536 g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" 537 } 538 if b2 { 539 h31(g18()) // ERROR "live at call to convT: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$" 540 } 541 if b3 { 542 panic(g18()) 543 } 544 print(b3) 545 } 546 547 func g31(interface{}) 548 func h31(...interface{}) 549 550 // non-escaping partial functions passed to function call should die on return 551 552 type T32 int 553 554 func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$" 555 *t++ 556 } 557 558 var t32 T32 559 560 func f32(b bool) { 561 if b { 562 call32(t32.Inc) // ERROR "stack object .autotmp_[0-9]+ struct \{" 563 } 564 call32(t32.Inc) 565 call32(t32.Inc) 566 } 567 568 //go:noescape 569 func call32(func()) 570 571 // temporaries introduced during if conditions and && || expressions 572 // should die once the condition has been acted upon. 573 574 var m33 map[interface{}]int 575 576 func f33() { 577 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 578 printnl() 579 return 580 } else { 581 printnl() 582 } 583 printnl() 584 } 585 586 func f34() { 587 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$" 588 printnl() 589 return 590 } 591 printnl() 592 } 593 594 func f35() { 595 if m33[byteptr()] == 0 && // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 596 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 597 printnl() 598 return 599 } 600 printnl() 601 } 602 603 func f36() { 604 if m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 605 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 606 printnl() 607 return 608 } 609 printnl() 610 } 611 612 func f37() { 613 if (m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 614 m33[byteptr()] == 0) && // ERROR "stack object .autotmp_[0-9]+ interface \{\}" 615 m33[byteptr()] == 0 { 616 printnl() 617 return 618 } 619 printnl() 620 } 621 622 // select temps should disappear in the case bodies 623 624 var c38 chan string 625 626 func fc38() chan string 627 func fi38(int) *string 628 func fb38() *bool 629 630 func f38(b bool) { 631 // we don't care what temps are printed on the lines with output. 632 // we care that the println lines have no live variables 633 // and therefore no output. 634 if b { 635 select { // ERROR "live at call to selectgo:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ \[4\]runtime.scase$" 636 case <-fc38(): 637 printnl() 638 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$" 639 printnl() 640 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$" 641 printnl() 642 case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to f[ibc]38:( .autotmp_[0-9]+)+$" 643 printnl() 644 } 645 printnl() 646 } 647 printnl() 648 } 649 650 // issue 8097: mishandling of x = x during return. 651 652 func f39() (x []int) { 653 x = []int{1} 654 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$" 655 return x 656 } 657 658 func f39a() (x []int) { 659 x = []int{1} 660 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$" 661 return 662 } 663 664 func f39b() (x [10]*int) { 665 x = [10]*int{} 666 x[0] = new(int) // ERROR "live at call to newobject: x$" 667 printnl() // ERROR "live at call to printnl: x$" 668 return x 669 } 670 671 func f39c() (x [10]*int) { 672 x = [10]*int{} 673 x[0] = new(int) // ERROR "live at call to newobject: x$" 674 printnl() // ERROR "live at call to printnl: x$" 675 return 676 } 677 678 // issue 8142: lost 'addrtaken' bit on inlined variables. 679 // no inlining in this test, so just checking that non-inlined works. 680 681 type T40 struct { 682 m map[int]int 683 } 684 685 //go:noescape 686 func useT40(*T40) 687 688 func newT40() *T40 { 689 ret := T40{} 690 ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$" 691 return &ret 692 } 693 694 func good40() { 695 ret := T40{} // ERROR "stack object ret T40$" 696 ret.m = make(map[int]int) // ERROR "live at call to rand(32)?: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ (runtime.hmap|internal/runtime/maps.Map)$" 697 t := &ret 698 printnl() // ERROR "live at call to printnl: ret$" 699 // Note: ret is live at the printnl because the compiler moves &ret 700 // from before the printnl to after. 701 useT40(t) 702 } 703 704 func bad40() { 705 t := newT40() 706 _ = t 707 printnl() 708 } 709 710 func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$" 711 ddd2(x, y) // ERROR "stack object .autotmp_[0-9]+ \[2\]\*int$" 712 printnl() 713 // Note: no .?autotmp live at printnl. See issue 16996. 714 } 715 func ddd2(a ...*int) { // ERROR "live at entry to ddd2: a$" 716 sink = a[0] 717 } 718 719 // issue 16016: autogenerated wrapper should have arguments live 720 type T struct{} 721 722 func (*T) Foo(ptr *int) {} 723 724 type R struct{ *T } 725 726 // issue 18860: output arguments must be live all the time if there is a defer. 727 // In particular, at printint r must be live. 728 func f41(p, q *int) (r *int) { // ERROR "live at entry to f41: p q$" 729 r = p 730 defer func() { 731 recover() 732 }() 733 printint(0) // ERROR "live at call to printint: .autotmp_[0-9]+ q r$" 734 r = q 735 return // ERROR "live at call to f41.func1: .autotmp_[0-9]+ r$" 736 } 737 738 func f42() { 739 var p, q, r int 740 f43([]*int{&p, &q, &r}) // ERROR "stack object .autotmp_[0-9]+ \[3\]\*int$" 741 f43([]*int{&p, &r, &q}) 742 f43([]*int{&q, &p, &r}) 743 } 744 745 //go:noescape 746 func f43(a []*int) 747 748 // Assigning to a sub-element that makes up an entire local variable 749 // should clobber that variable. 750 func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f" 751 type T struct { 752 s [1][2]*int 753 } 754 ret := T{} // ERROR "stack object ret T" 755 ret.s[0] = f() 756 return ret 757 } 758 759 func 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" 760 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" 761 runtime.KeepAlive(a) 762 runtime.KeepAlive(b) 763 runtime.KeepAlive(c) 764 runtime.KeepAlive(d) 765 runtime.KeepAlive(e) 766 runtime.KeepAlive(f) 767 runtime.KeepAlive(g) 768 runtime.KeepAlive(h) 769 runtime.KeepAlive(i) 770 runtime.KeepAlive(j) 771 runtime.KeepAlive(k) 772 runtime.KeepAlive(l) 773 } 774 775 //go:noinline 776 func f46(a, b, c, d, e, f, g, h, i, j, k, l *byte) { 777 } 778