Source file test/live_regabi.go

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

View as plain text