Source file test/live.go

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

View as plain text