Home | History | Annotate | Download | only in test
      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