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