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 for arrays and some large things 8 9 package foo 10 11 var Ssink *string 12 13 type U [2]*string 14 15 func bar(a, b *string) U { // ERROR "leaking param: a to result ~r2 level=0$" "leaking param: b to result ~r2 level=0$" 16 return U{a, b} 17 } 18 19 func foo(x U) U { // ERROR "leaking param: x to result ~r1 level=0$" 20 return U{x[1], x[0]} 21 } 22 23 func bff(a, b *string) U { // ERROR "leaking param: a to result ~r2 level=0$" "leaking param: b to result ~r2 level=0$" 24 return foo(foo(bar(a, b))) 25 } 26 27 func tbff1() *string { 28 a := "cat" 29 b := "dog" // ERROR "moved to heap: b$" 30 u := bff(&a, &b) // ERROR "tbff1 &a does not escape$" "tbff1 &b does not escape$" 31 _ = u[0] 32 return &b // ERROR "&b escapes to heap$" 33 } 34 35 // BAD: need fine-grained analysis to track u[0] and u[1] differently. 36 func tbff2() *string { 37 a := "cat" // ERROR "moved to heap: a$" 38 b := "dog" // ERROR "moved to heap: b$" 39 u := bff(&a, &b) // ERROR "&a escapes to heap$" "&b escapes to heap$" 40 _ = u[0] 41 return u[1] 42 } 43 44 func car(x U) *string { // ERROR "leaking param: x to result ~r1 level=0$" 45 return x[0] 46 } 47 48 // BAD: need fine-grained analysis to track x[0] and x[1] differently. 49 func fun(x U, y *string) *string { // ERROR "leaking param: x to result ~r2 level=0$" "leaking param: y to result ~r2 level=0$" 50 x[0] = y 51 return x[1] 52 } 53 54 func fup(x *U, y *string) *string { // ERROR "leaking param: x to result ~r2 level=1$" "leaking param: y$" 55 x[0] = y // leaking y to heap is intended 56 return x[1] 57 } 58 59 func fum(x *U, y **string) *string { // ERROR "leaking param: x to result ~r2 level=1$" "leaking param content: y$" 60 x[0] = *y 61 return x[1] 62 } 63 64 func fuo(x *U, y *U) *string { // ERROR "leaking param: x to result ~r2 level=1$" "leaking param content: y$" 65 x[0] = y[0] 66 return x[1] 67 } 68 69 // These two tests verify that: 70 // small array literals are stack allocated; 71 // pointers stored in small array literals do not escape; 72 // large array literals are heap allocated; 73 // pointers stored in large array literals escape. 74 func hugeLeaks1(x **string, y **string) { // ERROR "leaking param content: x" "hugeLeaks1 y does not escape" "mark escaped content: x" 75 a := [10]*string{*y} 76 _ = a 77 // 4 x 4,000,000 exceeds MaxStackVarSize, therefore it must be heap allocated if pointers are 4 bytes or larger. 78 b := [4000000]*string{*x} // ERROR "moved to heap: b" 79 _ = b 80 } 81 82 func hugeLeaks2(x *string, y *string) { // ERROR "leaking param: x" "hugeLeaks2 y does not escape" 83 a := [10]*string{y} 84 _ = a 85 // 4 x 4,000,000 exceeds MaxStackVarSize, therefore it must be heap allocated if pointers are 4 bytes or larger. 86 b := [4000000]*string{x} // ERROR "moved to heap: b" 87 _ = b 88 } 89 90 // BAD: x need not leak. 91 func doesNew1(x *string, y *string) { // ERROR "leaking param: x" "leaking param: y" 92 a := new([10]*string) // ERROR "new\(\[10\]\*string\) does not escape" 93 a[0] = x 94 b := new([65537]*string) // ERROR "new\(\[65537\]\*string\) escapes to heap" 95 b[0] = y 96 } 97 98 type a10 struct { 99 s *string 100 i [10]int32 101 } 102 103 type a65537 struct { 104 s *string 105 i [65537]int32 106 } 107 108 // BAD: x need not leak. 109 func doesNew2(x *string, y *string) { // ERROR "leaking param: x" "leaking param: y" 110 a := new(a10) // ERROR "new\(a10\) does not escape" 111 a.s = x 112 b := new(a65537) // ERROR "new\(a65537\) escapes to heap" 113 b.s = y 114 } 115 116 // BAD: x need not leak. 117 func doesMakeSlice(x *string, y *string) { // ERROR "leaking param: x" "leaking param: y" 118 a := make([]*string, 10) // ERROR "make\(\[\]\*string, 10\) does not escape" 119 a[0] = x 120 b := make([]*string, 65537) // ERROR "make\(\[\]\*string, 65537\) escapes to heap" 121 b[0] = y 122 } 123