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