Home | History | Annotate | Download | only in fixedbugs
      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 "FooN 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" "leaking param content: 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 "TFooN &i does not escape" "TFooN &j does not escape" "TFooN ... 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 "&k escapes to heap" "&i escapes to heap" "&j escapes to heap" "TFooNx ... 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 "&i escapes to heap" "&j escapes to heap" "&k escapes to heap" "... 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 "&i escapes to heap" "&j escapes to heap" "... 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       // ERROR "&a escapes to heap"
     87 	FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooI ... argument does not escape"
     88 }
     89 
     90 func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r1 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       // ERROR "TFooJ1 &a does not escape"
    111 	FooJ(a, b, c) // ERROR "TFooJ1 a does not escape" "TFooJ1 b does not escape" "TFooJ1 c does not escape" "TFooJ1 ... argument does not escape"
    112 }
    113 
    114 func TFooJ2() {
    115 	a := int32(1) // ERROR "moved to heap: a"
    116 	b := "cat"
    117 	c := &a               // ERROR "&a escapes to heap"
    118 	isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooJ2 ... 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 ~r1 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                                           // ERROR "&a escapes to heap"
    147 	fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooK2 &\[4\]interface {} literal does not escape"
    148 	isink = FooK(fs)
    149 }
    150 
    151 func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~r1 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                     // ERROR "&a escapes to heap"
    172 	s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooL2 \[\]interface {} literal does not escape"
    173 	isink = FooL(s)
    174 }
    175