Source file test/fixedbugs/issue12006.go

     1  // errorcheck -0 -m -l
     2  
     3  // Copyright 2015 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Test escape analysis through ... parameters.
     8  
     9  package foo
    10  
    11  func FooN(vals ...*int) (s int) { // ERROR "vals does not escape"
    12  	for _, v := range vals {
    13  		s += *v
    14  	}
    15  	return s
    16  }
    17  
    18  // Append forces heap allocation and copies entries in vals to heap, therefore they escape to heap.
    19  func FooNx(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param content: vals"
    20  	vals = append(vals, x)
    21  	return FooN(vals...)
    22  }
    23  
    24  var sink []*int
    25  
    26  func FooNy(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param: vals"
    27  	vals = append(vals, x)
    28  	sink = vals
    29  	return FooN(vals...)
    30  }
    31  
    32  func FooNz(vals ...*int) (s int) { // ERROR "leaking param: vals"
    33  	sink = vals
    34  	return FooN(vals...)
    35  }
    36  
    37  func TFooN() {
    38  	for i := 0; i < 1000; i++ {
    39  		var i, j int
    40  		FooN(&i, &j) // ERROR "... argument does not escape"
    41  	}
    42  }
    43  
    44  func TFooNx() {
    45  	for i := 0; i < 1000; i++ {
    46  		var i, j, k int   // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
    47  		FooNx(&k, &i, &j) // ERROR "... argument does not escape"
    48  	}
    49  }
    50  
    51  func TFooNy() {
    52  	for i := 0; i < 1000; i++ {
    53  		var i, j, k int   // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
    54  		FooNy(&k, &i, &j) // ERROR "... argument escapes to heap"
    55  	}
    56  }
    57  
    58  func TFooNz() {
    59  	for i := 0; i < 1000; i++ {
    60  		var i, j int  // ERROR "moved to heap: i" "moved to heap: j"
    61  		FooNz(&i, &j) // ERROR "... argument escapes to heap"
    62  	}
    63  }
    64  
    65  var isink *int32
    66  
    67  func FooI(args ...interface{}) { // ERROR "leaking param content: args"
    68  	for i := 0; i < len(args); i++ {
    69  		switch x := args[i].(type) {
    70  		case nil:
    71  			println("is nil")
    72  		case int32:
    73  			println("is int32")
    74  		case *int32:
    75  			println("is *int32")
    76  			isink = x
    77  		case string:
    78  			println("is string")
    79  		}
    80  	}
    81  }
    82  
    83  func TFooI() {
    84  	a := int32(1) // ERROR "moved to heap: a"
    85  	b := "cat"
    86  	c := &a
    87  	FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "... argument does not escape"
    88  }
    89  
    90  func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r0 level=1"
    91  	for i := 0; i < len(args); i++ {
    92  		switch x := args[i].(type) {
    93  		case nil:
    94  			println("is nil")
    95  		case int32:
    96  			println("is int32")
    97  		case *int32:
    98  			println("is *int32")
    99  			return x
   100  		case string:
   101  			println("is string")
   102  		}
   103  	}
   104  	return nil
   105  }
   106  
   107  func TFooJ1() {
   108  	a := int32(1)
   109  	b := "cat"
   110  	c := &a
   111  	FooJ(a, b, c) // ERROR "a does not escape" "b does not escape" "... argument does not escape"
   112  }
   113  
   114  func TFooJ2() {
   115  	a := int32(1) // ERROR "moved to heap: a"
   116  	b := "cat"
   117  	c := &a
   118  	isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "... argument does not escape"
   119  }
   120  
   121  type fakeSlice struct {
   122  	l int
   123  	a *[4]interface{}
   124  }
   125  
   126  func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r0 level=1"
   127  	for i := 0; i < args.l; i++ {
   128  		switch x := (*args.a)[i].(type) {
   129  		case nil:
   130  			println("is nil")
   131  		case int32:
   132  			println("is int32")
   133  		case *int32:
   134  			println("is *int32")
   135  			return x
   136  		case string:
   137  			println("is string")
   138  		}
   139  	}
   140  	return nil
   141  }
   142  
   143  func TFooK2() {
   144  	a := int32(1) // ERROR "moved to heap: a"
   145  	b := "cat"
   146  	c := &a
   147  	fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "&\[4\]interface {}{...} does not escape"
   148  	isink = FooK(fs)
   149  }
   150  
   151  func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~r0 level=1"
   152  	for i := 0; i < len(args); i++ {
   153  		switch x := args[i].(type) {
   154  		case nil:
   155  			println("is nil")
   156  		case int32:
   157  			println("is int32")
   158  		case *int32:
   159  			println("is *int32")
   160  			return x
   161  		case string:
   162  			println("is string")
   163  		}
   164  	}
   165  	return nil
   166  }
   167  
   168  func TFooL2() {
   169  	a := int32(1) // ERROR "moved to heap: a"
   170  	b := "cat"
   171  	c := &a
   172  	s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "\[\]interface {}{...} does not escape"
   173  	isink = FooL(s)
   174  }
   175  

View as plain text