github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/test/live_ssa.go (about) 1 // +build amd64 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(b1, b2 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 b1 == false { 55 printint(0) // ERROR "live at call to printint: x y$" 56 return 57 } 58 59 if b2 { 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$" 87 if b2 { 88 printint(1) // x not live here 89 return 90 } 91 for { 92 printint(**z) // ERROR "live at call to printint: x$" 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.data x.type$" 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 var sink *int 188 189 func f11c() *int { 190 p := new(int) 191 sink = p // prevent stack allocation, otherwise p is rematerializeable 192 if b { 193 // Unlike previous, the cases in this select fall through, 194 // so we can get to the println, so p is not dead. 195 printint(1) // ERROR "live at call to printint: p$" 196 select { // ERROR "live at call to newselect: autotmp_[0-9]+ p$" "live at call to selectgo: autotmp_[0-9]+ p$" 197 case <-c: // ERROR "live at call to selectrecv: autotmp_[0-9]+ p$" 198 case <-c: // ERROR "live at call to selectrecv: autotmp_[0-9]+ p$" 199 } 200 } 201 println(*p) 202 return nil 203 } 204 205 // similarly, select{} does not fall through. 206 // this used to have a spurious "live at entry to f12: ~r0". 207 208 func f12() *int { 209 if b { 210 select {} 211 } else { 212 return nil 213 } 214 } 215 216 // incorrectly placed VARDEF annotations can cause missing liveness annotations. 217 // this used to be missing the fact that s is live during the call to g13 (because it is 218 // needed for the call to h13). 219 220 func f13() { 221 s := g14() 222 s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$" 223 } 224 225 func g13(string) string 226 func h13(string, string) string 227 228 // more incorrectly placed VARDEF. 229 230 func f14() { 231 x := g14() 232 printstringpointer(&x) // ERROR "live at call to printstringpointer: x$" 233 } 234 235 func g14() string 236 237 func f15() { 238 var x string 239 _ = &x 240 x = g15() // ERROR "live at call to g15: x$" 241 printstring(x) // ERROR "live at call to printstring: x$" 242 } 243 244 func g15() string 245 246 // Checking that various temporaries do not persist or cause 247 // ambiguously live values that must be zeroed. 248 // The exact temporary names are inconsequential but we are 249 // trying to check that there is only one at any given site, 250 // and also that none show up in "ambiguously live" messages. 251 252 var m map[string]int 253 254 func f16() { 255 if b { 256 delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" 257 } 258 delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" 259 delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" 260 } 261 262 var m2s map[string]*byte 263 var m2 map[[2]string]*byte 264 var x2 [2]string 265 var bp *byte 266 267 func f17a() { 268 // value temporary only 269 if b { 270 m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 271 } 272 m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 273 m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 274 } 275 276 func f17b() { 277 // key temporary only 278 if b { 279 m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 280 } 281 m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 282 m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" 283 } 284 285 func f17c() { 286 // key and value temporaries 287 if b { 288 m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 289 } 290 m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 291 m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 292 } 293 294 func g18() [2]string 295 296 func f18() { 297 // key temporary for mapaccess. 298 // temporary introduced by orderexpr. 299 var z *byte 300 if b { 301 z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 302 } 303 z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 304 z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 305 printbytepointer(z) 306 } 307 308 var ch chan *byte 309 310 func f19() { 311 // dest temporary for channel receive. 312 var z *byte 313 314 if b { 315 z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" 316 } 317 z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" 318 z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" 319 printbytepointer(z) 320 } 321 322 func f20() { 323 // src temporary for channel send 324 if b { 325 ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" 326 } 327 ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" 328 ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" 329 } 330 331 func f21() { 332 // key temporary for mapaccess using array literal key. 333 var z *byte 334 if b { 335 z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 336 } 337 z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 338 z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 339 printbytepointer(z) 340 } 341 342 func f23() { 343 // key temporary for two-result map access using array literal key. 344 var z *byte 345 var ok bool 346 if b { 347 z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" 348 } 349 z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" 350 z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" 351 printbytepointer(z) 352 print(ok) 353 } 354 355 func f24() { 356 // key temporary for map access using array literal key. 357 // value temporary too. 358 if b { 359 m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 360 } 361 m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 362 m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" 363 } 364 365 // defer should not cause spurious ambiguously live variables 366 367 func f25(b bool) { 368 defer g25() 369 if b { 370 return 371 } 372 var x string 373 _ = &x 374 x = g15() // ERROR "live at call to g15: x$" 375 printstring(x) // ERROR "live at call to printstring: x$" 376 } // ERROR "live at call to deferreturn: x$" 377 378 func g25() 379 380 // non-escaping ... slices passed to function call should die on return, 381 // so that the temporaries do not stack and do not cause ambiguously 382 // live variables. 383 384 func f26(b bool) { 385 if b { 386 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" 387 } 388 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" 389 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" 390 printnl() 391 } 392 393 //go:noescape 394 func print26(...interface{}) 395 396 // non-escaping closures passed to function call should die on return 397 398 func f27(b bool) { 399 x := 0 400 if b { 401 call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" 402 } 403 call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" 404 call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" 405 printnl() 406 } 407 408 // but defer does escape to later execution in the function 409 410 func f27defer(b bool) { 411 x := 0 412 if b { 413 defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$" 414 } 415 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]+$" 416 printnl() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$" 417 } // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" 418 419 // and newproc (go) escapes to the heap 420 421 func f27go(b bool) { 422 x := 0 423 if b { 424 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newproc: &x$" 425 } 426 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" 427 printnl() 428 } 429 430 //go:noescape 431 func call27(func()) 432 433 // concatstring slice should die on return 434 435 var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string 436 437 func f28(b bool) { 438 if b { 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 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]+$" 442 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]+$" 443 } 444 445 // map iterator should die on end of range loop 446 447 func f29(b bool) { 448 if b { 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 } 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 for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$" 457 printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$" 458 } 459 } 460 461 // copy of array of pointers should die at end of range loop 462 463 var ptrarr [10]*int 464 465 func f30(b bool) { 466 // two live temps during print(p): 467 // the copy of ptrarr and the internal iterator pointer. 468 if b { 469 for _, p := range ptrarr { 470 printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$" 471 } 472 } 473 for _, p := range ptrarr { 474 printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$" 475 } 476 for _, p := range ptrarr { 477 printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$" 478 } 479 } 480 481 // conversion to interface should not leave temporary behind 482 483 func f31(b1, b2, b3 bool) { 484 if b1 { 485 g31("a") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to g31: autotmp_[0-9]+$" 486 } 487 if b2 { 488 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]+$" 489 } 490 if b3 { 491 panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$" 492 } 493 print(b3) 494 } 495 496 func g31(interface{}) 497 func h31(...interface{}) 498 499 // non-escaping partial functions passed to function call should die on return 500 501 type T32 int 502 503 func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$" 504 *t++ 505 } 506 507 var t32 T32 508 509 func f32(b bool) { 510 if b { 511 call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" 512 } 513 call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" 514 call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" 515 } 516 517 //go:noescape 518 func call32(func()) 519 520 // temporaries introduced during if conditions and && || expressions 521 // should die once the condition has been acted upon. 522 523 var m33 map[interface{}]int 524 525 func f33() { 526 if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 527 printnl() 528 return 529 } else { 530 printnl() 531 } 532 printnl() 533 } 534 535 func f34() { 536 if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 537 printnl() 538 return 539 } 540 printnl() 541 } 542 543 func f35() { 544 if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 545 printnl() 546 return 547 } 548 printnl() 549 } 550 551 func f36() { 552 if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 553 printnl() 554 return 555 } 556 printnl() 557 } 558 559 func f37() { 560 if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" 561 printnl() 562 return 563 } 564 printnl() 565 } 566 567 // select temps should disappear in the case bodies 568 569 var c38 chan string 570 571 func fc38() chan string 572 func fi38(int) *string 573 func fb38() *bool 574 575 func f38(b bool) { 576 // we don't care what temps are printed on the lines with output. 577 // we care that the println lines have no live variables 578 // and therefore no output. 579 if b { 580 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]+$" 581 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]+$" 582 printnl() 583 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]+$" 584 printnl() 585 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]+$" 586 printnl() 587 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]+$" 588 printnl() 589 } 590 printnl() 591 } 592 printnl() 593 } 594 595 // issue 8097: mishandling of x = x during return. 596 597 func f39() (x []int) { 598 x = []int{1} 599 printnl() // ERROR "live at call to printnl: autotmp_[0-9]+$" 600 return x 601 } 602 603 func f39a() (x []int) { 604 x = []int{1} 605 printnl() // ERROR "live at call to printnl: autotmp_[0-9]+$" 606 return 607 } 608 609 func f39b() (x [10]*int) { 610 x = [10]*int{} 611 x[0] = new(int) // ERROR "live at call to newobject: x$" 612 printnl() // ERROR "live at call to printnl: x$" 613 return x 614 } 615 616 func f39c() (x [10]*int) { 617 x = [10]*int{} 618 x[0] = new(int) // ERROR "live at call to newobject: x$" 619 printnl() // ERROR "live at call to printnl: x$" 620 return 621 } 622 623 // issue 8142: lost 'addrtaken' bit on inlined variables. 624 // no inlining in this test, so just checking that non-inlined works. 625 626 type T40 struct { 627 m map[int]int 628 } 629 630 func newT40() *T40 { 631 ret := T40{} 632 ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret$" 633 return &ret 634 } 635 636 func bad40() { 637 t := newT40() 638 _ = t 639 printnl() 640 } 641 642 func good40() { 643 ret := T40{} 644 ret.m = make(map[int]int) // ERROR "live at call to makemap: autotmp_[0-9]+ ret$" 645 t := &ret 646 printnl() // ERROR "live at call to printnl: autotmp_[0-9]+ ret$" 647 _ = t 648 }