Source file test/live_regabi.go

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

View as plain text