Source file test/live.go

     1  // errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off
     2  
     3  //go:build !ppc64 && !ppc64le && !goexperiment.regabiargs
     4  
     5  // ppc64 needs a better tighten pass to make f18 pass
     6  // rescheduling checks need to be turned off because there are some live variables across the inserted check call
     7  //
     8  // For register ABI, liveness info changes slightly. See live_regabi.go.
     9  
    10  // Copyright 2014 The Go Authors. All rights reserved.
    11  // Use of this source code is governed by a BSD-style
    12  // license that can be found in the LICENSE file.
    13  
    14  // liveness tests with inlining disabled.
    15  // see also live2.go.
    16  
    17  package main
    18  
    19  func printnl()
    20  
    21  //go:noescape
    22  func printpointer(**int)
    23  
    24  //go:noescape
    25  func printintpointer(*int)
    26  
    27  //go:noescape
    28  func printstringpointer(*string)
    29  
    30  //go:noescape
    31  func printstring(string)
    32  
    33  //go:noescape
    34  func printbytepointer(*byte)
    35  
    36  func printint(int)
    37  
    38  func f1() {
    39  	var x *int       // ERROR "stack object x \*int$"
    40  	printpointer(&x) // ERROR "live at call to printpointer: x$"
    41  	printpointer(&x)
    42  }
    43  
    44  func f2(b bool) {
    45  	if b {
    46  		printint(0) // nothing live here
    47  		return
    48  	}
    49  	var x *int       // ERROR "stack object x \*int$"
    50  	printpointer(&x) // ERROR "live at call to printpointer: x$"
    51  	printpointer(&x)
    52  }
    53  
    54  func f3(b1, b2 bool) {
    55  	// Here x and y are ambiguously live. In previous go versions they
    56  	// were marked as live throughout the function to avoid being
    57  	// poisoned in GODEBUG=gcdead=1 mode; this is now no longer the
    58  	// case.
    59  
    60  	printint(0)
    61  	if b1 == false {
    62  		printint(0)
    63  		return
    64  	}
    65  
    66  	if b2 {
    67  		var x *int       // ERROR "stack object x \*int$"
    68  		printpointer(&x) // ERROR "live at call to printpointer: x$"
    69  		printpointer(&x)
    70  	} else {
    71  		var y *int       // ERROR "stack object y \*int$"
    72  		printpointer(&y) // ERROR "live at call to printpointer: y$"
    73  		printpointer(&y)
    74  	}
    75  	printint(0) // nothing is live here
    76  }
    77  
    78  // The old algorithm treated x as live on all code that
    79  // could flow to a return statement, so it included the
    80  // function entry and code above the declaration of x
    81  // but would not include an indirect use of x in an infinite loop.
    82  // Check that these cases are handled correctly.
    83  
    84  func f4(b1, b2 bool) { // x not live here
    85  	if b2 {
    86  		printint(0) // x not live here
    87  		return
    88  	}
    89  	var z **int
    90  	x := new(int) // ERROR "stack object x \*int$"
    91  	*x = 42
    92  	z = &x
    93  	printint(**z) // ERROR "live at call to printint: x$"
    94  	if b2 {
    95  		printint(1) // x not live here
    96  		return
    97  	}
    98  	for {
    99  		printint(**z) // ERROR "live at call to printint: x$"
   100  	}
   101  }
   102  
   103  func f5(b1 bool) {
   104  	var z **int
   105  	if b1 {
   106  		x := new(int) // ERROR "stack object x \*int$"
   107  		*x = 42
   108  		z = &x
   109  	} else {
   110  		y := new(int) // ERROR "stack object y \*int$"
   111  		*y = 54
   112  		z = &y
   113  	}
   114  	printint(**z) // nothing live here
   115  }
   116  
   117  // confusion about the _ result used to cause spurious "live at entry to f6: _".
   118  
   119  func f6() (_, y string) {
   120  	y = "hello"
   121  	return
   122  }
   123  
   124  // confusion about addressed results used to cause "live at entry to f7: x".
   125  
   126  func f7() (x string) { // ERROR "stack object x string"
   127  	_ = &x
   128  	x = "hello"
   129  	return
   130  }
   131  
   132  // ignoring block returns used to cause "live at entry to f8: x, y".
   133  
   134  func f8() (x, y string) {
   135  	return g8()
   136  }
   137  
   138  func g8() (string, string)
   139  
   140  // ignoring block assignments used to cause "live at entry to f9: x"
   141  // issue 7205
   142  
   143  var i9 interface{}
   144  
   145  func f9() bool {
   146  	g8()
   147  	x := i9
   148  	y := interface{}(g18()) // ERROR "live at call to convT: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$"
   149  	i9 = y                  // make y escape so the line above has to call convT
   150  	return x != y
   151  }
   152  
   153  // liveness formerly confused by UNDEF followed by RET,
   154  // leading to "live at entry to f10: ~r1" (unnamed result).
   155  
   156  func f10() string {
   157  	panic(1)
   158  }
   159  
   160  // liveness formerly confused by select, thinking runtime.selectgo
   161  // can return to next instruction; it always jumps elsewhere.
   162  // note that you have to use at least two cases in the select
   163  // to get a true select; smaller selects compile to optimized helper functions.
   164  
   165  var c chan *int
   166  var b bool
   167  
   168  // this used to have a spurious "live at entry to f11a: ~r0"
   169  func f11a() *int {
   170  	select { // ERROR "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
   171  	case <-c:
   172  		return nil
   173  	case <-c:
   174  		return nil
   175  	}
   176  }
   177  
   178  func f11b() *int {
   179  	p := new(int)
   180  	if b {
   181  		// At this point p is dead: the code here cannot
   182  		// get to the bottom of the function.
   183  		// This used to have a spurious "live at call to printint: p".
   184  		printint(1) // nothing live here!
   185  		select {    // ERROR "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
   186  		case <-c:
   187  			return nil
   188  		case <-c:
   189  			return nil
   190  		}
   191  	}
   192  	println(*p)
   193  	return nil
   194  }
   195  
   196  var sink *int
   197  
   198  func f11c() *int {
   199  	p := new(int)
   200  	sink = p // prevent stack allocation, otherwise p is rematerializeable
   201  	if b {
   202  		// Unlike previous, the cases in this select fall through,
   203  		// so we can get to the println, so p is not dead.
   204  		printint(1) // ERROR "live at call to printint: p$"
   205  		select {    // ERROR "live at call to selectgo: p$" "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
   206  		case <-c:
   207  		case <-c:
   208  		}
   209  	}
   210  	println(*p)
   211  	return nil
   212  }
   213  
   214  // similarly, select{} does not fall through.
   215  // this used to have a spurious "live at entry to f12: ~r0".
   216  
   217  func f12() *int {
   218  	if b {
   219  		select {}
   220  	} else {
   221  		return nil
   222  	}
   223  }
   224  
   225  // incorrectly placed VARDEF annotations can cause missing liveness annotations.
   226  // this used to be missing the fact that s is live during the call to g13 (because it is
   227  // needed for the call to h13).
   228  
   229  func f13() {
   230  	s := g14()
   231  	s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$"
   232  }
   233  
   234  func g13(string) string
   235  func h13(string, string) string
   236  
   237  // more incorrectly placed VARDEF.
   238  
   239  func f14() {
   240  	x := g14() // ERROR "stack object x string$"
   241  	printstringpointer(&x)
   242  }
   243  
   244  func g14() 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  var mi map[interface{}]int
   254  
   255  // str and iface are used to ensure that a temp is required for runtime calls below.
   256  func str() string
   257  func iface() interface{}
   258  
   259  func f16() {
   260  	if b {
   261  		delete(mi, iface()) // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
   262  	}
   263  	delete(mi, iface())
   264  	delete(mi, iface())
   265  }
   266  
   267  var m2s map[string]*byte
   268  var m2 map[[2]string]*byte
   269  var x2 [2]string
   270  var bp *byte
   271  
   272  func f17a(p *byte) { // ERROR "live at entry to f17a: p$"
   273  	if b {
   274  		m2[x2] = p // ERROR "live at call to mapassign: p$"
   275  	}
   276  	m2[x2] = p // ERROR "live at call to mapassign: p$"
   277  	m2[x2] = p // ERROR "live at call to mapassign: p$"
   278  }
   279  
   280  func f17b(p *byte) { // ERROR "live at entry to f17b: p$"
   281  	// key temporary
   282  	if b {
   283  		m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
   284  	}
   285  	m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
   286  	m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
   287  }
   288  
   289  func f17c() {
   290  	// key and value temporaries
   291  	if b {
   292  		m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
   293  	}
   294  	m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
   295  	m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
   296  }
   297  
   298  func f17d() *byte
   299  
   300  func g18() [2]string
   301  
   302  func f18() {
   303  	// key temporary for mapaccess.
   304  	// temporary introduced by orderexpr.
   305  	var z *byte
   306  	if b {
   307  		z = m2[g18()] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
   308  	}
   309  	z = m2[g18()]
   310  	z = m2[g18()]
   311  	printbytepointer(z)
   312  }
   313  
   314  var ch chan *byte
   315  
   316  // byteptr is used to ensure that a temp is required for runtime calls below.
   317  func byteptr() *byte
   318  
   319  func f19() {
   320  	// dest temporary for channel receive.
   321  	var z *byte
   322  
   323  	if b {
   324  		z = <-ch // ERROR "stack object .autotmp_[0-9]+ \*byte$"
   325  	}
   326  	z = <-ch
   327  	z = <-ch // ERROR "live at call to chanrecv1: .autotmp_[0-9]+$"
   328  	printbytepointer(z)
   329  }
   330  
   331  func f20() {
   332  	// src temporary for channel send
   333  	if b {
   334  		ch <- byteptr() // ERROR "stack object .autotmp_[0-9]+ \*byte$"
   335  	}
   336  	ch <- byteptr()
   337  	ch <- byteptr()
   338  }
   339  
   340  func f21(x, y string) { // ERROR "live at entry to f21: x y"
   341  	// key temporary for mapaccess using array literal key.
   342  	var z *byte
   343  	if b {
   344  		z = m2[[2]string{x, y}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
   345  	}
   346  	z = m2[[2]string{"x", "y"}]
   347  	z = m2[[2]string{"x", "y"}]
   348  	printbytepointer(z)
   349  }
   350  
   351  func f21b() {
   352  	// key temporary for mapaccess using array literal key.
   353  	var z *byte
   354  	if b {
   355  		z = m2[[2]string{"x", "y"}]
   356  	}
   357  	z = m2[[2]string{"x", "y"}]
   358  	z = m2[[2]string{"x", "y"}]
   359  	printbytepointer(z)
   360  }
   361  
   362  func f23(x, y string) { // ERROR "live at entry to f23: x y"
   363  	// key temporary for two-result map access using array literal key.
   364  	var z *byte
   365  	var ok bool
   366  	if b {
   367  		z, ok = m2[[2]string{x, y}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
   368  	}
   369  	z, ok = m2[[2]string{"x", "y"}]
   370  	z, ok = m2[[2]string{"x", "y"}]
   371  	printbytepointer(z)
   372  	print(ok)
   373  }
   374  
   375  func f23b() {
   376  	// key temporary for two-result map access using array literal key.
   377  	var z *byte
   378  	var ok bool
   379  	if b {
   380  		z, ok = m2[[2]string{"x", "y"}]
   381  	}
   382  	z, ok = m2[[2]string{"x", "y"}]
   383  	z, ok = m2[[2]string{"x", "y"}]
   384  	printbytepointer(z)
   385  	print(ok)
   386  }
   387  
   388  func f24(x, y string) { // ERROR "live at entry to f24: x y"
   389  	// key temporary for map access using array literal key.
   390  	// value temporary too.
   391  	if b {
   392  		m2[[2]string{x, y}] = nil // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
   393  	}
   394  	m2[[2]string{"x", "y"}] = nil
   395  	m2[[2]string{"x", "y"}] = nil
   396  }
   397  
   398  func f24b() {
   399  	// key temporary for map access using array literal key.
   400  	// value temporary too.
   401  	if b {
   402  		m2[[2]string{"x", "y"}] = nil
   403  	}
   404  	m2[[2]string{"x", "y"}] = nil
   405  	m2[[2]string{"x", "y"}] = nil
   406  }
   407  
   408  // Non-open-coded defers should not cause autotmps.  (Open-coded defers do create extra autotmps).
   409  func f25(b bool) {
   410  	for i := 0; i < 2; i++ {
   411  		// Put in loop to make sure defer is not open-coded
   412  		defer g25()
   413  	}
   414  	if b {
   415  		return
   416  	}
   417  	var x string
   418  	x = g14()
   419  	printstring(x)
   420  	return
   421  }
   422  
   423  func g25()
   424  
   425  // non-escaping ... slices passed to function call should die on return,
   426  // so that the temporaries do not stack and do not cause ambiguously
   427  // live variables.
   428  
   429  func f26(b bool) {
   430  	if b {
   431  		print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "stack object .autotmp_[0-9]+ \[3\]interface \{\}$"
   432  	}
   433  	print26((*int)(nil), (*int)(nil), (*int)(nil))
   434  	print26((*int)(nil), (*int)(nil), (*int)(nil))
   435  	printnl()
   436  }
   437  
   438  //go:noescape
   439  func print26(...interface{})
   440  
   441  // non-escaping closures passed to function call should die on return
   442  
   443  func f27(b bool) {
   444  	x := 0
   445  	if b {
   446  		call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
   447  	}
   448  	call27(func() { x++ })
   449  	call27(func() { x++ })
   450  	printnl()
   451  }
   452  
   453  // but defer does escape to later execution in the function
   454  
   455  func f27defer(b bool) {
   456  	x := 0
   457  	if b {
   458  		defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
   459  	}
   460  	defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
   461  	printnl()                    // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+"
   462  	return                       // ERROR "live at indirect call: .autotmp_[0-9]+"
   463  }
   464  
   465  // and newproc (go) escapes to the heap
   466  
   467  func f27go(b bool) {
   468  	x := 0
   469  	if b {
   470  		go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: &x .autotmp_[0-9]+$" "live at call to newproc: &x$" // allocate two closures, the func literal, and the wrapper for go
   471  	}
   472  	go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: .autotmp_[0-9]+$" // allocate two closures, the func literal, and the wrapper for go
   473  	printnl()
   474  }
   475  
   476  //go:noescape
   477  func call27(func())
   478  
   479  // concatstring slice should die on return
   480  
   481  var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
   482  
   483  func f28(b bool) {
   484  	if b {
   485  		printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "stack object .autotmp_[0-9]+ \[10\]string$"
   486  	}
   487  	printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10)
   488  	printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10)
   489  }
   490  
   491  // map iterator should die on end of range loop
   492  
   493  func f29(b bool) {
   494  	if b {
   495  		for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ (runtime.hiter|internal/runtime/maps.Iter)$"
   496  			printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
   497  		}
   498  	}
   499  	for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$"
   500  		printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
   501  	}
   502  	for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$"
   503  		printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
   504  	}
   505  }
   506  
   507  // copy of array of pointers should die at end of range loop
   508  var pstructarr [10]pstruct
   509  
   510  // Struct size chosen to make pointer to element in pstructarr
   511  // not computable by strength reduction.
   512  type pstruct struct {
   513  	intp *int
   514  	_    [8]byte
   515  }
   516  
   517  func f30(b bool) {
   518  	// live temp during printintpointer(p):
   519  	// the internal iterator pointer if a pointer to pstruct in pstructarr
   520  	// can not be easily computed by strength reduction.
   521  	if b {
   522  		for _, p := range pstructarr { // ERROR "stack object .autotmp_[0-9]+ \[10\]pstruct$"
   523  			printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
   524  		}
   525  	}
   526  	for _, p := range pstructarr {
   527  		printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
   528  	}
   529  	for _, p := range pstructarr {
   530  		printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
   531  	}
   532  }
   533  
   534  // conversion to interface should not leave temporary behind
   535  
   536  func f31(b1, b2, b3 bool) {
   537  	if b1 {
   538  		g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
   539  	}
   540  	if b2 {
   541  		h31(g18()) // ERROR "live at call to convT: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$"
   542  	}
   543  	if b3 {
   544  		panic(g18())
   545  	}
   546  	print(b3)
   547  }
   548  
   549  func g31(interface{})
   550  func h31(...interface{})
   551  
   552  // non-escaping partial functions passed to function call should die on return
   553  
   554  type T32 int
   555  
   556  func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$"
   557  	*t++
   558  }
   559  
   560  var t32 T32
   561  
   562  func f32(b bool) {
   563  	if b {
   564  		call32(t32.Inc) // ERROR "stack object .autotmp_[0-9]+ struct \{"
   565  	}
   566  	call32(t32.Inc)
   567  	call32(t32.Inc)
   568  }
   569  
   570  //go:noescape
   571  func call32(func())
   572  
   573  // temporaries introduced during if conditions and && || expressions
   574  // should die once the condition has been acted upon.
   575  
   576  var m33 map[interface{}]int
   577  
   578  func f33() {
   579  	if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
   580  		printnl()
   581  		return
   582  	} else {
   583  		printnl()
   584  	}
   585  	printnl()
   586  }
   587  
   588  func f34() {
   589  	if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
   590  		printnl()
   591  		return
   592  	}
   593  	printnl()
   594  }
   595  
   596  func f35() {
   597  	if m33[byteptr()] == 0 && // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
   598  		m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
   599  		printnl()
   600  		return
   601  	}
   602  	printnl()
   603  }
   604  
   605  func f36() {
   606  	if m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
   607  		m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
   608  		printnl()
   609  		return
   610  	}
   611  	printnl()
   612  }
   613  
   614  func f37() {
   615  	if (m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
   616  		m33[byteptr()] == 0) && // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
   617  		m33[byteptr()] == 0 {
   618  		printnl()
   619  		return
   620  	}
   621  	printnl()
   622  }
   623  
   624  // select temps should disappear in the case bodies
   625  
   626  var c38 chan string
   627  
   628  func fc38() chan string
   629  func fi38(int) *string
   630  func fb38() *bool
   631  
   632  func f38(b bool) {
   633  	// we don't care what temps are printed on the lines with output.
   634  	// we care that the println lines have no live variables
   635  	// and therefore no output.
   636  	if b {
   637  		select { // ERROR "live at call to selectgo:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ \[4\]runtime.scase$"
   638  		case <-fc38():
   639  			printnl()
   640  		case fc38() <- *fi38(1): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$"
   641  			printnl()
   642  		case *fi38(2) = <-fc38(): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$"
   643  			printnl()
   644  		case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to f[ibc]38:( .autotmp_[0-9]+)+$"
   645  			printnl()
   646  		}
   647  		printnl()
   648  	}
   649  	printnl()
   650  }
   651  
   652  // issue 8097: mishandling of x = x during return.
   653  
   654  func f39() (x []int) {
   655  	x = []int{1}
   656  	printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$"
   657  	return x
   658  }
   659  
   660  func f39a() (x []int) {
   661  	x = []int{1}
   662  	printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$"
   663  	return
   664  }
   665  
   666  func f39b() (x [10]*int) {
   667  	x = [10]*int{}
   668  	x[0] = new(int) // ERROR "live at call to newobject: x$"
   669  	printnl()       // ERROR "live at call to printnl: x$"
   670  	return x
   671  }
   672  
   673  func f39c() (x [10]*int) {
   674  	x = [10]*int{}
   675  	x[0] = new(int) // ERROR "live at call to newobject: x$"
   676  	printnl()       // ERROR "live at call to printnl: x$"
   677  	return
   678  }
   679  
   680  // issue 8142: lost 'addrtaken' bit on inlined variables.
   681  // no inlining in this test, so just checking that non-inlined works.
   682  
   683  type T40 struct {
   684  	m map[int]int
   685  }
   686  
   687  //go:noescape
   688  func useT40(*T40)
   689  
   690  func newT40() *T40 {
   691  	ret := T40{}
   692  	ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$"
   693  	return &ret
   694  }
   695  
   696  func good40() {
   697  	ret := T40{}              // ERROR "stack object ret T40$"
   698  	ret.m = make(map[int]int) // ERROR "live at call to rand(32)?: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ (runtime.hmap|internal/runtime/maps.Map)$"
   699  	t := &ret
   700  	printnl() // ERROR "live at call to printnl: ret$"
   701  	// Note: ret is live at the printnl because the compiler moves &ret
   702  	// from before the printnl to after.
   703  	useT40(t)
   704  }
   705  
   706  func bad40() {
   707  	t := newT40()
   708  	_ = t
   709  	printnl()
   710  }
   711  
   712  func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$"
   713  	ddd2(x, y) // ERROR "stack object .autotmp_[0-9]+ \[2\]\*int$"
   714  	printnl()
   715  	// Note: no .?autotmp live at printnl.  See issue 16996.
   716  }
   717  func ddd2(a ...*int) { // ERROR "live at entry to ddd2: a$"
   718  	sink = a[0]
   719  }
   720  
   721  // issue 16016: autogenerated wrapper should have arguments live
   722  type T struct{}
   723  
   724  func (*T) Foo(ptr *int) {}
   725  
   726  type R struct{ *T }
   727  
   728  // issue 18860: output arguments must be live all the time if there is a defer.
   729  // In particular, at printint r must be live.
   730  func f41(p, q *int) (r *int) { // ERROR "live at entry to f41: p q$"
   731  	r = p
   732  	defer func() {
   733  		recover()
   734  	}()
   735  	printint(0) // ERROR "live at call to printint: .autotmp_[0-9]+ q r$"
   736  	r = q
   737  	return // ERROR "live at call to f41.func1: .autotmp_[0-9]+ r$"
   738  }
   739  
   740  func f42() {
   741  	var p, q, r int
   742  	f43([]*int{&p, &q, &r}) // ERROR "stack object .autotmp_[0-9]+ \[3\]\*int$"
   743  	f43([]*int{&p, &r, &q})
   744  	f43([]*int{&q, &p, &r})
   745  }
   746  
   747  //go:noescape
   748  func f43(a []*int)
   749  
   750  // Assigning to a sub-element that makes up an entire local variable
   751  // should clobber that variable.
   752  func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f"
   753  	type T struct {
   754  		s [1][2]*int
   755  	}
   756  	ret := T{} // ERROR "stack object ret T"
   757  	ret.s[0] = f()
   758  	return ret
   759  }
   760  

View as plain text