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