Source file test/live_regabi.go

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

View as plain text