live.go 16.2 KB
Newer Older
Russ Cox's avatar
Russ Cox committed
1
// errorcheck -0 -l -live -wb=0
2 3 4 5 6

// Copyright 2014 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

7 8 9
// liveness tests with inlining disabled.
// see also live2.go.

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
package main

func f1() {
	var x *int
	print(&x) // ERROR "live at call to printpointer: x$"
	print(&x) // ERROR "live at call to printpointer: x$"
}

func f2(b bool) {
	if b {
		print(0) // nothing live here
		return
	}
	var x *int
	print(&x) // ERROR "live at call to printpointer: x$"
	print(&x) // ERROR "live at call to printpointer: x$"
}

func f3(b bool) {
29 30 31 32 33
	// Because x and y are ambiguously live, they appear
	// live throughout the function, to avoid being poisoned
	// in GODEBUG=gcdead=1 mode.

	print(0) // ERROR "live at call to printint: x y$"
34
	if b == false {
35
		print(0) // ERROR "live at call to printint: x y$"
36 37 38 39 40
		return
	}

	if b {
		var x *int
41 42
		print(&x) // ERROR "live at call to printpointer: x y$"
		print(&x) // ERROR "live at call to printpointer: x y$"
43 44
	} else {
		var y *int
45 46
		print(&y) // ERROR "live at call to printpointer: x y$"
		print(&y) // ERROR "live at call to printpointer: x y$"
47
	}
Russ Cox's avatar
Russ Cox committed
48
	print(0) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
}

// The old algorithm treated x as live on all code that
// could flow to a return statement, so it included the
// function entry and code above the declaration of x
// but would not include an indirect use of x in an infinite loop.
// Check that these cases are handled correctly.

func f4(b1, b2 bool) { // x not live here
	if b2 {
		print(0) // x not live here
		return
	}
	var z **int
	x := new(int)
	*x = 42
	z = &x
	print(**z) // ERROR "live at call to printint: x z$"
	if b2 {
		print(1) // ERROR "live at call to printint: x$"
		return
	}
	for {
		print(**z) // ERROR "live at call to printint: x z$"
	}
}

func f5(b1 bool) {
	var z **int
	if b1 {
		x := new(int)
		*x = 42
		z = &x
	} else {
		y := new(int)
		*y = 54
		z = &y
	}
Russ Cox's avatar
Russ Cox committed
87
	print(**z) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
88
}
89 90 91 92 93 94 95

// confusion about the _ result used to cause spurious "live at entry to f6: _".

func f6() (_, y string) {
	y = "hello"
	return
}
96 97 98 99 100 101 102 103 104

// confusion about addressed results used to cause "live at entry to f7: x".

func f7() (x string) {
	_ = &x
	x = "hello"
	return
}

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
// ignoring block returns used to cause "live at entry to f8: x, y".

func f8() (x, y string) {
	return g8()
}

func g8() (string, string)

// ignoring block assignments used to cause "live at entry to f9: x"
// issue 7205

var i9 interface{}

func f9() bool {
	g8()
	x := i9
121 122 123 124
	// using complex number in comparison so that
	// there is always a convT2E, no matter what the
	// interface rules are.
	return x != 99.0i // ERROR "live at call to convT2E: x"
125
}
126 127 128 129 130 131 132 133

// liveness formerly confused by UNDEF followed by RET,
// leading to "live at entry to f10: ~r1" (unnamed result).

func f10() string {
	panic(1)
}

134 135 136 137 138 139 140 141 142 143
// liveness formerly confused by select, thinking runtime.selectgo
// can return to next instruction; it always jumps elsewhere.
// note that you have to use at least two cases in the select
// to get a true select; smaller selects compile to optimized helper functions.

var c chan *int
var b bool

// this used to have a spurious "live at entry to f11a: ~r0"
func f11a() *int {
144
	select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp"
145 146 147 148 149 150 151 152 153 154 155 156 157 158
	case <-c: // ERROR "live at call to selectrecv: autotmp"
		return nil
	case <-c: // ERROR "live at call to selectrecv: autotmp"
		return nil
	}
}

func f11b() *int {
	p := new(int)
	if b {
		// At this point p is dead: the code here cannot
		// get to the bottom of the function.
		// This used to have a spurious "live at call to printint: p".
		print(1) // nothing live here!
159
		select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp"
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
		case <-c: // ERROR "live at call to selectrecv: autotmp"
			return nil
		case <-c: // ERROR "live at call to selectrecv: autotmp"
			return nil
		}
	}
	println(*p)
	return nil
}

func f11c() *int {
	p := new(int)
	if b {
		// Unlike previous, the cases in this select fall through,
		// so we can get to the println, so p is not dead.
		print(1) // ERROR "live at call to printint: p"
176
		select { // ERROR "live at call to newselect: autotmp.* p" "live at call to selectgo: autotmp.* p"
177 178 179 180 181 182 183 184 185 186 187 188 189
		case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
		case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
		}
	}
	println(*p)
	return nil
}

// similarly, select{} does not fall through.
// this used to have a spurious "live at entry to f12: ~r0".

func f12() *int {
	if b {
190
		select {}
191 192 193 194
	} else {
		return nil
	}
}
195 196 197 198 199 200 201 202 203 204 205 206

// incorrectly placed VARDEF annotations can cause missing liveness annotations.
// this used to be missing the fact that s is live during the call to g13 (because it is
// needed for the call to h13).

func f13() {
	s := "hello"
	s = h13(s, g13(s)) // ERROR "live at call to g13: s"
}

func g13(string) string
func h13(string, string) string
Russ Cox's avatar
Russ Cox committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220

// more incorrectly placed VARDEF.

func f14() {
	x := g14()
	print(&x) // ERROR "live at call to printpointer: x"
}

func g14() string

func f15() {
	var x string
	_ = &x
	x = g15() // ERROR "live at call to g15: x"
221
	print(x)  // ERROR "live at call to printstring: x"
Russ Cox's avatar
Russ Cox committed
222 223 224
}

func g15() string
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292

// Checking that various temporaries do not persist or cause
// ambiguously live values that must be zeroed.
// The exact temporary names are inconsequential but we are
// trying to check that there is only one at any given site,
// and also that none show up in "ambiguously live" messages.

var m map[string]int

func f16() {
	if b {
		delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
	}
	delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
	delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
}

var m2s map[string]*byte
var m2 map[[2]string]*byte
var x2 [2]string
var bp *byte

func f17a() {
	// value temporary only
	if b {
		m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
	}
	m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
	m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
}

func f17b() {
	// key temporary only
	if b {
		m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
	}
	m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
	m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
}

func f17c() {
	// key and value temporaries
	if b {
		m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
	}
	m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
	m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
}

func g18() [2]string

func f18() {
	// key temporary for mapaccess.
	// temporary introduced by orderexpr.
	var z *byte
	if b {
		z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
	}
	z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
	z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
	print(z)
}

var ch chan *byte

func f19() {
	// dest temporary for channel receive.
	var z *byte
293

294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
	if b {
		z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
	}
	z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
	z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
	print(z)
}

func f20() {
	// src temporary for channel send
	if b {
		ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
	}
	ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
	ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
}

func f21() {
	// key temporary for mapaccess using array literal key.
	var z *byte
	if b {
		z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
	}
	z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
	z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
	print(z)
}

func f23() {
	// key temporary for two-result map access using array literal key.
	var z *byte
	var ok bool
	if b {
		z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
	}
	z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
	z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
	print(z, ok)
}

func f24() {
	// key temporary for map access using array literal key.
	// value temporary too.
	if b {
		m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
	}
	m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
	m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
}
343 344 345 346 347 348 349 350 351 352 353

// defer should not cause spurious ambiguously live variables

func f25(b bool) {
	defer g25()
	if b {
		return
	}
	var x string
	_ = &x
	x = g15() // ERROR "live at call to g15: x"
354
	print(x)  // ERROR "live at call to printstring: x"
355 356 357
} // ERROR "live at call to deferreturn: x"

func g25()
358

359 360 361 362 363 364
// non-escaping ... slices passed to function call should die on return,
// so that the temporaries do not stack and do not cause ambiguously
// live variables.

func f26(b bool) {
	if b {
365
		print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
366
	}
367 368
	print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
	print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
369 370 371 372 373 374 375 376 377 378 379
	println()
}

//go:noescape
func print26(...interface{})

// non-escaping closures passed to function call should die on return

func f27(b bool) {
	x := 0
	if b {
380
		call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
381
	}
382 383
	call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
	call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
384 385 386 387 388 389 390 391
	println()
}

// but defer does escape to later execution in the function

func f27defer(b bool) {
	x := 0
	if b {
392
		defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
393
	}
394 395
	defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
	println()                    // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
396 397 398 399 400 401 402
} // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"

// and newproc (go) escapes to the heap

func f27go(b bool) {
	x := 0
	if b {
403
		go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$"
404
	}
405
	go call27(func() { x++ }) // ERROR "live at call to newobject: &x"
406
	println()
407 408 409 410 411 412 413 414 415 416 417
}

//go:noescape
func call27(func())

// concatstring slice should die on return

var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string

func f28(b bool) {
	if b {
418
		print(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]+$"
419
	}
420 421 422
	print(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]+$"
	print(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]+$"
}
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458

// map iterator should die on end of range loop

func f29(b bool) {
	if b {
		for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
			print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
		}
	}
	for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
		print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
	}
	for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
		print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
	}
}

// copy of array of pointers should die at end of range loop

var ptrarr [10]*int

func f30(b bool) {
	// two live temps during print(p):
	// the copy of ptrarr and the internal iterator pointer.
	if b {
		for _, p := range ptrarr {
			print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
		}
	}
	for _, p := range ptrarr {
		print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
	}
	for _, p := range ptrarr {
		print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
	}
}
459 460 461 462 463 464 465 466

// conversion to interface should not leave temporary behind

func f31(b1, b2, b3 bool) {
	if b1 {
		g31("a") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to g31: autotmp_[0-9]+$"
	}
	if b2 {
Keith Randall's avatar
Keith Randall committed
467
		h31("b") // ERROR "live at call to newobject: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$"
468 469
	}
	if b3 {
470
		panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$"
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
	}
	print(b3)
}

func g31(interface{})
func h31(...interface{})

// non-escaping partial functions passed to function call should die on return

type T32 int

func (t *T32) Inc() { // ERROR "live at entry"
	*t++
}

var t32 T32

func f32(b bool) {
	if b {
		call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$"
	}
	call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$"
	call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$"
}

//go:noescape
func call32(func())

// temporaries introduced during if conditions and && || expressions
// should die once the condition has been acted upon.

var m33 map[interface{}]int

func f33() {
	if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
		println()
		return
	} else {
		println()
	}
	println()
}

func f34() {
	if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
		println()
		return
	}
	println()
}

func f35() {
	if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
		println()
		return
	}
	println()
}

func f36() {
	if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
		println()
		return
	}
	println()
}

func f37() {
	if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
		println()
		return
	}
	println()
}

// select temps should disappear in the case bodies

var c38 chan string

func fc38() chan string
func fi38(int) *string
func fb38() *bool

func f38(b bool) {
	// we don't care what temps are printed on the lines with output.
	// we care that the println lines have no live variables
	// and therefore no output.
	if b {
		select { // ERROR "live at call"
		case <-fc38(): // ERROR "live at call"
			println()
		case fc38() <- *fi38(1): // ERROR "live at call"
			println()
		case *fi38(2) = <-fc38(): // ERROR "live at call"
			println()
		case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call"
			println()
		}
		println()
	}
	println()
}
Russ Cox's avatar
Russ Cox committed
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588

// issue 8097: mishandling of x = x during return.

func f39() (x []int) {
	x = []int{1}
	println() // ERROR "live at call to printnl: x"
	return x
}

func f39a() (x []int) {
	x = []int{1}
	println() // ERROR "live at call to printnl: x"
	return
}

func f39b() (x [10]*int) {
589 590 591
	x = [10]*int{}
	x[0] = new(int) // ERROR "live at call to newobject: x"
	println()       // ERROR "live at call to printnl: x"
Russ Cox's avatar
Russ Cox committed
592 593 594 595
	return x
}

func f39c() (x [10]*int) {
596 597 598
	x = [10]*int{}
	x[0] = new(int) // ERROR "live at call to newobject: x"
	println()       // ERROR "live at call to printnl: x"
Russ Cox's avatar
Russ Cox committed
599 600
	return
}
601 602 603 604 605 606 607 608 609

// issue 8142: lost 'addrtaken' bit on inlined variables.
// no inlining in this test, so just checking that non-inlined works.

type T40 struct {
	m map[int]int
}

func newT40() *T40 {
610 611
	ret := T40{}
	ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret"
612 613 614 615 616 617
	return &ret
}

func bad40() {
	t := newT40()
	_ = t
618
	println()
619 620 621
}

func good40() {
622 623
	ret := T40{}
	ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
624 625 626 627
	t := &ret
	println() // ERROR "live at call to printnl: ret"
	_ = t
}