Source file test/escape_array.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 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 ~r0 level=0$" "leaking param: b to result ~r0 level=0$"
    16  	return U{a, b}
    17  }
    18  
    19  func foo(x U) U { // ERROR "leaking param: x to result ~r0 level=0$"
    20  	return U{x[1], x[0]}
    21  }
    22  
    23  func bff(a, b *string) U { // ERROR "leaking param: a to result ~r0 level=0$" "leaking param: b to result ~r0 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)
    31  	_ = u[0]
    32  	return &b
    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)
    40  	_ = u[0]
    41  	return u[1]
    42  }
    43  
    44  func car(x U) *string { // ERROR "leaking param: x to result ~r0 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 ~r0 level=0$" "leaking param: y to result ~r0 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 ~r0 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 ~r0 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 ~r0 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" "y does not escape"
    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" "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  
   124  func nonconstArray() {
   125  	n := 32
   126  	s1 := make([]int, n)    // ERROR "make\(\[\]int, n\) escapes to heap"
   127  	s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap"
   128  	_, _ = s1, s2
   129  }
   130  

View as plain text