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